我正在寻找一种方法来在使用其属性时始终拦截特定类的实例。
例如,如果MyTestClass被拦截......这会触发拦截:
var myObj = new MyTestClass();
var x = myObj.SomeProperty;
然后拦截方法“get_SomeProperty”.. 但是我使用Unity看到的所有示例都要求我通过container.Resolve();“管道”MyTestClass实例的创建。我想避免这样......它有可能吗?我很确定我之前曾经使用Castle.DynamicProxy做过类似的事情..但是我当前的应用程序恰好安装了Unity,所以它尽可能地重新使用Unity,这是一个好主意。
不使用container.Resolve()的另一个原因是我的这个实例也可以在MVC动作中创建,它没有对容器的逻辑引用。我不认为将MyTestClass注入构造函数的参数是一个非常好的主意..
BR, INX
答案 0 :(得分:2)
好的,所以这里......
首先假设我们有这个域类定义:
public interface IInterceptableClass
{
string FirstName { get; set; }
string LastName { get; }
string GetLastName();
}
public class InterceptableClass : IInterceptableClass
{
public string FirstName { get; set; }
public string LastName { get; private set; }
public InterceptableClass()
{
LastName = "lastname";
}
public string GetLastName()
{
return LastName;
}
}
假设你有一个像这样定义的简单拦截器行为:
internal class SampleInterceptorBehavior : IInterceptionBehavior
{
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
// this invokes the method at the tip of the method chain
var result = getNext()(input, getNext);
// method executed with no exceptions (yay)
if (result.Exception == null)
{
//input.Target
Console.WriteLine($"intercepting: target={input.Target.ToString()}, method={input.MethodBase.Name}");
}
else // boo..!
{
// handle exception here
Console.WriteLine($"error! message={result.Exception?.Message}");
}
return result;
}
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public bool WillExecute { get { return true; } }
}
你可以通过Unity
这样连线:
static void Main(string[] args)
{
var container = new UnityContainer();
container.AddNewExtension<Interception>();
container.RegisterType<IInterceptableClass, InterceptableClass>(
new Interceptor<TransparentProxyInterceptor>(),
new InterceptionBehavior<SampleInterceptorBehavior>());
var myInstance = container.Resolve<IInterceptableClass>();
// just want to illustrate that privae sets are not supported...
myInstance.FirstName = "firstname";
var lastname = myInstance.GetLastName();
Console.ReadLine();
}
请注意,如果不使用Unity连接拦截,则必须手动执行此操作。对于一次性,一些开发者可能更喜欢它,但在实践中,我总是发现这条路是不可持续的,并且有多个拦截,非常残酷。所以,如果可以,请始终使用Unity。
如果你绝对不得不绕过Unity,那么你就是这样做的:
var manualInstance = Intercept.ThroughProxy<IInterceptableClass>(
new InterceptableClass(), // <-- this could be an already-existing instance as well...
new TransparentProxyInterceptor(),
new IInterceptionBehavior[]
{
new SampleInterceptorBehavior()
});
manualInstance.FirstName = "firstname";
var lastname = manualInstance.GetLastName();
答案 1 :(得分:0)
答案 2 :(得分:0)
这就是我最终做的......
UnityConfig(MVC)中的RegisterTypes
osascript is not allowed assistive access
IDependencyResolverFactory
container.RegisterType<IDependencyResolverFactory, DependencyResolverFactory>
(
new InjectionConstructor(container)
);
container.RegisterType<ISearchModel, SearchModel>(
new Interceptor(typeof(VirtualMethodInterceptor)),
new InterceptionBehavior(typeof(SearchModelInterceptionBehaviour)));
DependencyResolverFactory public class DependencyResolverFactory:IDependencyResolverFactory { 私人IUnityContainer _container;
public interface IDependencyResolverFactory
{
TEntity Resolve<TEntity>();
}
然后只需在我的控制器中:
public DependencyResolverFactory(IUnityContainer container)
{
_container = container;
}
public TEntity Resolve<TEntity>()
{
return _container.Resolve<TEntity>();
}
public TEntity Resolve<TEntity>(TEntity type) where TEntity : class
{
return (TEntity)_container.Resolve(type.GetType());
}
}
希望这能让除了我以外的人有所了解:P