使用表达式树通过代理现有实现来实现接口
Use Expression tree to implement interface by proxying existing implementation
假设我有以下接口和两个实现。
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 方法来 "configure" 代理。这基本上是一个列表或字典,每个项目都应该是方法和类型。在使用表达式树生成代理时应该检查要使用的实现。
所以
说说,DutchPerson
午餐,英语人
GetProxy 方法将 return(伪代码)
public class MergedInstance : IPerson
{
public void Talk() {
return DutchPerson.Talk()
}
public Lunch() {
EnglishPerson.Lunch()
}
}
我主要想要这个是因为代理的实现包含很多方法,我希望能够使用功能标志在实现之间切换。
所以我是不是看错了,使用表达式树这是否合理可行。我正在使用 .NET 4.5.1。
通过 System.Reflection.Emit
+ Expression
树来实现是 quite/very 复杂的......但是如果你有一个不变的 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;
}
在运行时创建代理 class 的唯一优点是:
您可以使用任何界面(因此它可以与 IPerson
、IAnimal
、...一起使用),在运行时选择。逻辑可以通过其他方法 and/or 的委托注入,由 XML 或其他配置对象
读取
您的 MergedInstance
class 中的每个方法可以有少于一个引用(根据配置,您需要的引用数量在单个所有方法使用一个,每个方法使用一个,所以最大值相同,变化的是最小值)
我不认为表情树是你的朋友。阅读运行时编织(代理)。一个非常容易理解和使用的框架是例如 Castle DynamicProxy (http://www.castleproject.org/projects/dynamicproxy/)。阅读一些 howtos,你会发现自己很惊讶。
如果性能真的很关键,我仍然会尝试组合而不是动态生成 类,但是您可以尝试 Reflection.Emit 方式(正如@xantos 所建议的),它可以一旦 类 生成(它本身并不快),就可以用更快的运行时间完成同样的事情。祝你好运
假设我有以下接口和两个实现。
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 方法来 "configure" 代理。这基本上是一个列表或字典,每个项目都应该是方法和类型。在使用表达式树生成代理时应该检查要使用的实现。
所以
说说,DutchPerson 午餐,英语人
GetProxy 方法将 return(伪代码)
public class MergedInstance : IPerson
{
public void Talk() {
return DutchPerson.Talk()
}
public Lunch() {
EnglishPerson.Lunch()
}
}
我主要想要这个是因为代理的实现包含很多方法,我希望能够使用功能标志在实现之间切换。
所以我是不是看错了,使用表达式树这是否合理可行。我正在使用 .NET 4.5.1。
通过 System.Reflection.Emit
+ Expression
树来实现是 quite/very 复杂的......但是如果你有一个不变的 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;
}
在运行时创建代理 class 的唯一优点是:
您可以使用任何界面(因此它可以与
IPerson
、IAnimal
、...一起使用),在运行时选择。逻辑可以通过其他方法 and/or 的委托注入,由 XML 或其他配置对象 读取
您的
MergedInstance
class 中的每个方法可以有少于一个引用(根据配置,您需要的引用数量在单个所有方法使用一个,每个方法使用一个,所以最大值相同,变化的是最小值)
我不认为表情树是你的朋友。阅读运行时编织(代理)。一个非常容易理解和使用的框架是例如 Castle DynamicProxy (http://www.castleproject.org/projects/dynamicproxy/)。阅读一些 howtos,你会发现自己很惊讶。
如果性能真的很关键,我仍然会尝试组合而不是动态生成 类,但是您可以尝试 Reflection.Emit 方式(正如@xantos 所建议的),它可以一旦 类 生成(它本身并不快),就可以用更快的运行时间完成同样的事情。祝你好运