假设我有以下界面和两个实现。
public interface IPerson
{
string Talk();
void Lunch();
}
public class DutchPerson : IPerson
{
public string Talk()
{
return "Ik spreek Nederlands.";
}
public void Lunch()
{
EatBroodjeKroket();
}
private void EatBroodjeKroket()
{
}
}
public class EnglishPerson : IPerson
{
public string Talk()
{
return "I speak English.";
}
public void Lunch()
{
EatFishAndChips();
}
private void EatFishAndChips()
{
}
}
public class ImplementationBuilder<T>
{
private Dictionary<Type, IPerson> _instances;
/// <summary>
///
/// </summary>
/// <param name="instances">Instances that will be used in proxy</param>
public ImplementationBuilder(Dictionary<Type, IPerson> instances)
{
_instances = instances;
}
public void Setup()
{
}
/// <summary>
/// this should return the generated instance
/// </summary>
public IPerson GetProxy()
{
return null;
}
}
我想做的是使用表达式树创建一个新的实现,并混合和匹配两个(或更多)实现中的方法。基本上我想创建一个实现IPerson的代理。所以我传入将要使用的实例,并且我想使用Setup方法来“配置”代理。这基本上是一个列表或字典,每个项目应该是方法和类型。应该在使用表达式树生成代理时检查要使用的实现。
所以用
Talk,DutchPerson 午餐,EnglishPerson
GetProxy方法将返回(伪代码)
public class MergedInstance : IPerson
{
public void Talk() {
return DutchPerson.Talk()
}
public Lunch() {
EnglishPerson.Lunch()
}
}
我主要想要这个,因为代理的实现包含很多方法,我希望能够使用功能标志在实现之间切换。
所以我以错误的方式看待它,使用Expression树甚至是合理可行的。我正在使用.NET 4.5.1。
答案 0 :(得分:2)
通过System.Reflection.Emit
+ Expression
树来完成它非常/非常复杂......但如果你有一个不变的IPerson
,你可以:
public class MergedInstance : IPerson
{
public IPerson TalkIPerson { get; set; }
public IPerson LunchIPerson { get; set; }
public void Talk()
{
TalkIPerson.Talk();
}
public Lunch() {
LunchIPerson.Lunch();
}
}
等等
然后您的GetProxy
可以
public IPerson GetProxy()
{
var merged = MergedInstance();
merged.TalkIPerson = ...
merged.LunchIPerson = ...
return merged;
}
在运行时创建代理类的唯一好处是:
您可以使用任何界面(因此它可以与IPerson
,IAnimal
,...)一起使用,在运行时选择。逻辑可以通过其他方法通过委托注入和/或通过XML或其他配置对象读取
对于MergedInstance
类中的每个方法,您可以使用少于一个引用(取决于配置,您需要的引用数在所有方法使用的单个引用之间是可变的,1对于每种方法,所以最大值是相同的,它是最小的变化)
答案 1 :(得分:1)
我不认为表达树是你的朋友。读运行时编织(代理)。一个非常容易理解和使用的框架是例如Castle DynamicProxy(http://www.castleproject.org/projects/dynamicproxy/)。阅读一些howtos,你会发现自己很惊讶。
如果性能真的很关键,我仍然会尝试编写而不是动态生成类,但是你可以尝试使用Reflection.Emit方式(如@xantos建议的那样),这可以通过更快的运行时间来完成相同的操作。生成类(本身并不快)。祝你好运