我拥有的是:
MethodP()
我想要达到的目标是:
调用(或者使用任何DI框架注入)
MethodA()
中的 MethodQ()
,
MethodB()
中的MethodR()
,
MethodC()
中的Class PQR
,
但不在Class ABC
上展开Class ABC
,反之亦然。
或者,如果不修改Class PQR
,我可以修改Prism
。
我确实检查了一些现有的DI框架,如Autofac
,Unity
,Class ABC
,但要使用它们,我必须修改ABC
(添加一些属性,扩展到某些接口等) 。),我不想这样做。
我怎样才能做到这一点?
更新1:
班级PQR
和班级<h2>Header 1</h2>
<p>Some text</p>
...
<p>Some text</p>
<h3>Sub-header 1</h3>
<p>Some text</p>
...
<p>Some text</p>
<h2>Header 2</h2>
没有任何共同的超类/接口。
答案 0 :(得分:2)
这个的一般设计模式是Decorator Pattern。您可以通过为IABC
:
ABC
来执行此操作
interface IAbc {
void MethodA();
void MethodB();
void MethodC();
}
现在,您可以为IABC
定义一个能够拦截&#39;的装饰器。在致电ABC
之前拨打PQR
并致电ABC
:
class AbcToPqrDecorator : IAbc
{
private readonly PQR pqr;
private readonly IAbc decorated;
public AbcToPqrDecorator(PQR pqr, IAbc decorated) {
this.pqr = pqr;
this.decorated = decorated;
}
public void MethodA() {
pqr.MethodP();
decorated.MethodA();
}
public void MethodB() {
pqr.MethodQ();
decorated.MethodB();
}
public void MethodC() {
pqr.MethodR();
decorated.MethodC();
}
}
您可以按如下方式创建对象图:
IAbc abc = new AbcToPqrDecorator(new PQR(), new ABC());
重要提示:如果您发现使用装饰器会导致大量开销(因为您需要定义许多具有相同行为但不同接口的装饰器实现),这表明您违反了SOLID和缺少一个共同的抽象。您的评论表明情况确实如此:
我有50多个像ABC这样的课程。
作为如何设计系统的示例,this article描述了如何设计系统的一部分,以便包装诸如MethodA()
,MethodB()
之类的操作变得微不足道和MethodC()
只有一个通用装饰器,只需要定义一次。
答案 1 :(得分:0)
我真的看到你的PQR
类持有event
而不是方法,因为你想在另一个方法中注入一个方法:
class PQR
{
public event EventHandler MethodP;
public event EventHandler MethodQ;
public event EventHandler MethodR;
public PQR()
{
MethodP += delegate { MethodP1(); };
MethodQ += delegate { MethodQ1(); };
MethodR += delegate { MethodR1(); };
}
private void MethodP1()
{
Console.WriteLine("In method P");
}
private void MethodQ1()
{
Console.WriteLine("In method Q");
}
private void MethodR1()
{
Console.WriteLine("In method R");
}
}
然后你可以简单地为事件添加方法:
var abc = new ABC();
var pqr = new PQR();
pqr.MethodP += delegate { abc.MethodA(); };
pqr.MethodQ += delegate { abc.MethodB(); };
pqr.MethodR += delegate { abc.MethodC(); };
这样你就可以让你的ABC
课程不受影响。
答案 2 :(得分:0)
如何处理这类东西的一种方法是Castle.DynamicProxy。有一些缺点 - 如果你不实现类而不是接口,方法需要virtual
才能拦截工作:
//Install-Package Castle.DynamicProxy
public class Interceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.Out.WriteLine("Intercepting: " + invocation.Method.Name);
invocation.Proceed();
}
}
public class ABC
{
public virtual void MethodA()
{
Console.WriteLine("In method A");
}
public void MethodB()
{
Console.WriteLine("In method B");
}
}
用法:
var generator = new ProxyGenerator();
var abc = generator.CreateClassProxy<ABC>(new Interceptor());
// "Intercepting: MethodA"
// "In method A"
abc.MethodA();
// oops - not virtual method - no interception
// "In method B"
abc.MethodB();
PostSharp功能更强大,AOP魔法发生在构建之后(因此性能更高),不幸的是它不是免费的。
答案 3 :(得分:0)
我正在研究NConcern .NET AOP Framework,这是一个新的开源AOP框架,在运行时工作,没有任何工厂/代理模式和反射性能成本。它似乎能够处理你需要的东西。
请看一下。
public class MonkeyPatch : IAspect
{
static public void Patch(MethodInfo oldMethod, MethodInfo newMethod)
{
//update monkey patch dictionary
MonkeyPatch.m_Dictionary[oldMethod] = newMethod;
//release previous monkey patch for target method.
Aspect.Release<MonkeyPatch>(oldMethod);
//weave monkey patch for target method.
Aspect.Weave<MonkeyPatch>(oldMethod);
}
static private Dictionary<MethodInfo, MethodInfo> m_Dictionary = new Dictionary<MethodInfo, MethodInfo>();
public IEnumerable<IAdvice> Advise(MethodInfo method)
{
if (MonkeyPatch.m_Dictionary.ContainsKey(_Method))
{
yield return Advice(MonkeyPatch.m_Dictionary[_Method]);
}
}
}
用法
static public void main(string[] args)
{
//MonkeyPatch.Patch(typeof(ABC).GetMethod("A"), typeof(PQR).GetMethod("P"));
MonkeyPatch.Patch(Metadata<ABC>.Method(_ABC => _ABC.A()), Metadata<PQR>.Method(_PQR=> _PQR.P()));
//MonkeyPatch.Patch(typeof(ABC).GetMethod("B"), typeof(PQR).GetMethod("Q"));
MonkeyPatch.Patch(Metadata<ABC>.Method(_ABC => _ABC.B()), Metadata<PQR>.Method(_PQR=> _PQR.Q()));
//MonkeyPatch.Patch(typeof(ABC).GetMethod("C"), typeof(PQR).GetMethod("R"));
MonkeyPatch.Patch(Metadata<ABC>.Method(_ABC => _ABC.C()), Metadata<PQR>.Method(_PQR=> _PQR.R()));
}