Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/apache/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在运行时生成接口实现_C#_Mvvm_Castle Windsor_Interceptor_Proxy Classes - Fatal编程技术网

C# 在运行时生成接口实现

C# 在运行时生成接口实现,c#,mvvm,castle-windsor,interceptor,proxy-classes,C#,Mvvm,Castle Windsor,Interceptor,Proxy Classes,我想问一下,是否有一个库允许在运行时生成接口的实现,并具有下面所示的一些附加功能 假设我有这样的界面: interface ICustomer { string Name {get;set;} string IAddress { get;set; } } interface IAddress { string Street {get;set;} } ICustomer customer = someLibrary.Create<ICustomer>(boo

我想问一下,是否有一个库允许在运行时生成接口的实现,并具有下面所示的一些附加功能

假设我有这样的界面:

interface ICustomer
{
    string Name {get;set;}
    string IAddress { get;set; }
}

interface IAddress
{
    string Street {get;set;}
}
ICustomer customer = someLibrary.Create<ICustomer>(bool createSubObjects)
我想这样做:

interface ICustomer
{
    string Name {get;set;}
    string IAddress { get;set; }
}

interface IAddress
{
    string Street {get;set;}
}
ICustomer customer = someLibrary.Create<ICustomer>(bool createSubObjects)

有什么好主意吗?

也许像这样的方法会奏效:

public T Create<T>(bool createSubObjects)
    {
        T MyICustomer = default(T);
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        sb.Append(@"
            using System;
            using System.Collections.Generic;
            using System.Linq;

            namespace MyNameSpace
            {
                public class RuntimeCustomer:NotifyPropertyChanged,").Append(typeof(T).FullName).Append(@"
                {
                    string name;").Append(createSubObjects ? @"
                    IAddress address = new RuntimeAddress(); " :@"
                    IAddress address = null;").Append(@"

                    public string Name 
                    {
                        get { return name; }
                        set { SetProperty(ref name, value); }
                    }
                    public IAddress Address
                    { 
                        get { return address; }
                        set { SetProperty(ref address, value) }
                    }
                }

                class RuntimeAddress : NotifyPropertyChanged, IAddress
                {
                    string street;
                    public string Street 
                    {
                            get { return street; }
                            set { SetProperty(ref,street, value) }
                    }
                }
             }");

        Dictionary<string, string> providerOptions = new Dictionary<string, string>();
        providerOptions["CompilerVersion"] = "v3.5"; //OR YOUR VERSION
        Microsoft.CSharp.CSharpCodeProvider provider = new Microsoft.CSharp.CSharpCodeProvider(providerOptions);

        System.CodeDom.Compiler.CompilerParameters parameters = new System.CodeDom.Compiler.CompilerParameters();
        parameters.GenerateExecutable = false;
        parameters.GenerateInMemory = true;
        parameters.IncludeDebugInformation = true;
        parameters.ReferencedAssemblies.Add("System.dll");
        parameters.ReferencedAssemblies.Add(typeof(System.Linq.Enumerable).Assembly.Location);
        parameters.ReferencedAssemblies.Add(System.Reflection.Assembly.GetCallingAssembly().Location);
        parameters.ReferencedAssemblies.Add(System.Reflection.Assembly.GetExecutingAssembly().Location);

        System.CodeDom.Compiler.CompilerResults results = provider.CompileAssemblyFromSource(parameters, sb.ToString());

        if (results.Errors.Count == 0)
        {
            Type generated = results.CompiledAssembly.GetType("MyNameSpace.RuntimeAddress");
            MyICustomer = (T)generated.GetConstructor(Type.EmptyTypes).Invoke(null);
        }
        else
        {
          //Do something
        }

        return MyICustomer; 
    }
public T创建(bool createSubObjects)
{
T MyicCustomer=默认值(T);
System.Text.StringBuilder sb=新的System.Text.StringBuilder();
某人附加(@)
使用制度;
使用System.Collections.Generic;
使用System.Linq;
名称空间MyNameSpace
{
公共类RuntimeCustomer:NotifyPropertyChanged,“).Append(typeof(T).FullName).Append(@”
{
字符串名称;“”。追加(createSubObjects?@)
IAddress address=新运行时地址();“:@”
IadAddress=null;“”。追加(@)
公共字符串名
{
获取{返回名称;}
set{SetProperty(ref name,value);}
}
公开演说
{ 
获取{返回地址;}
set{SetProperty(ref地址,值)}
}
}
类运行时地址:NotifyPropertyChanged,IAddress
{
弦街;;
公共弦街
{
获取{返回街;}
set{SetProperty(ref,street,value)}
}
}
}");
Dictionary providerOptions=新建字典();
providerOptions[“CompilerVersion”]=“v3.5”;//或您的版本
Microsoft.CSharp.CSharpCodeProvider provider=新的Microsoft.CSharp.CSharpCodeProvider(providerOptions);
System.CodeDom.Compiler.CompilerParameters parameters=new System.CodeDom.Compiler.CompilerParameters();
parameters.GenerateExecutable=false;
parameters.GenerateInMemory=true;
parameters.includedebuginfo=true;
parameters.referencedAssembly.Add(“System.dll”);
parameters.referencedAssembly.Add(typeof(System.Linq.Enumerable).Assembly.Location);
parameters.ReferencedAssembly.Add(System.Reflection.Assembly.GetCallingAssembly().Location);
parameters.ReferencedAssembly.Add(System.Reflection.Assembly.GetExecutionGassembly().Location);
System.CodeDom.Compiler.CompilerResults results=provider.compileasemblyFromSource(参数,sb.ToString());
如果(results.Errors.Count==0)
{
生成的类型=results.CompiledAssembly.GetType(“MyNameSpace.RuntimeAddress”);
MyicCustomer=(T)生成的.GetConstructor(Type.EmptyTypes).Invoke(null);
}
其他的
{
//做点什么
}
返回我的客户;
}

作为一种选择,您可以自己伪造。它将完成所有这些,甚至更多,而不需要发出你自己的IL。看见
只需获取它并向类中添加属性,或从INotifyPropertyChanged派生。

正如jure所说,您可以使用DynamicProxy实现此功能,但它将应用于接口的JIT实现。看看这个:

PostSharp也擅长此用例,但它是通过编译时编织和运行时JIT来完成的


希望这有帮助

也许像这样@jure你能举例说明在这种情况下如何使用它吗?我以前看过Castle和LinFu,但没发现对那个案子有用谢谢你的回答。我相信这样的IL发射或编译是必须的,您的代码可以很好地工作,但是这个接口只包含示例,所以我认为一些库是以通用方式这样做的exists@user2542183您可以创建自己的库,并通过将代码文本作为参数传递给create函数使其更加灵活。因为必须在某个地方定义某个接口的实现。投赞成票或打分作为回答:)?哦,是的,我最终会的,但我希望这样的事情已经存在