使用表达式树通过代理现有实现实现接口
本文关键字:实现 代理 接口 表达式 | 更新日期: 2023-09-27 17:49:18
假设我有以下接口和两个实现:
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方法来"配置"代理。这基本上是一个List或Dictionary,每一项都应该是Method和Type。在使用表达式树生成代理时,应该检查要使用的实现。
与
说话,DutchPerson午餐,EnglishPerson
GetProxy方法将返回(伪代码)
public class MergedInstance : IPerson
{
public void Talk() {
return DutchPerson.Talk()
}
public Lunch() {
EnglishPerson.Lunch()
}
}
我主要想要这个,因为代理实现包含很多方法,我希望能够使用特性标志在实现之间切换。
所以我看它在错误的方式,这甚至是合理可行的使用表达式树。我使用的是。net 4.5.1
通过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之间是可变的,因此最大值是相同的,这是最小的变化)
我不认为表达式树是你的朋友。读取运行时编织(代理)。一个非常容易理解和使用的框架是Castle DynamicProxy (http://www.castleproject.org/projects/dynamicproxy/)。读一些howtos,你会发现自己很惊讶。
如果性能真的很关键,我仍然会尝试组合而不是动态地生成类,但是您可以尝试反射。Emit方法(如@xantos所建议的),可以在生成类后更快地运行时完成相同的工作(这本身并不快)。祝你好运