我想问一下是否有一个库允许在运行时生成接口的实现,并提供下面说明的一些附加功能。
假设我有这样的界面:
interface ICustomer
{
string Name {get;set;}
string IAddress { get;set; }
}
interface IAddress
{
string Street {get;set;}
}
我想做那样的事情:
ICustomer customer = someLibrary.Create<ICustomer>(bool createSubObjects)
其中Create<T>()
方法将在运行时创建这样的实现:
class RuntimeCustomer : NotifyPropertyChanged,ICustomer
//NotifyPropertyChanged would be hand written class
{
string name;
IAddress address = new RuntimeAddress();
//if createSubObjects == false then `IAddress address = null`
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) }
}
}
请问好吗?
答案 0 :(得分:2)
正如jure所说,你可以使用DynamicProxy来实现这一点,但它将应用于JIT实现的接口。看看这个:http://jonas.follesoe.no/2009/12/23/automatic-inotifypropertychanged-using-dynamic-proxy/
PostSharp也擅长此用例,但它是通过编译时编织与运行时JIT进行的。 http://www.postsharp.net/aspects/examples/inotifypropertychanged
希望这有帮助
答案 1 :(得分:0)
也许这样的事情会起作用:
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;
}
答案 2 :(得分:0)
作为替代方案,你可以做到这一点。它将完成所有这些以及更多,而无需发出自己的IL。见https://github.com/Fody/PropertyChanged 只需Nuget它并为您的类添加一个属性,或从INotifyPropertyChanged派生。