2015-10-02 88 views
0

林寻找一种方式尽快它的属性被用来拦截总是一个特定的类的实例..使用Unity拦截实例?在全球范围内拦截特定类型的

例如,如果MyTestClass将intercepted..this将触发拦截:

var myObj = new MyTestClass(); 
var x = myObj.SomeProperty; 

那会然后截距方法“get_SomeProperty” .. 然而,我已经使用Unity看到的所有实施例中需要我“管”通过container.Resolve创建MyTestClass的实例的(); ..我想避免这一点..是否有可能?..我很确定我做了这样的事情使用Castle.DynamicProxy一旦bef矿石..但是我目前的应用程序恰好安装了Unity,所以它尽可能地重新使用Unity是一个好主意。

不使用container.Resolve()的另一个原因是,我的这个实例也可能在MVC动作中创建,它没有对容器的逻辑引用..我不认为注入MyTestClass作为一个参数设置为构造将是一个非常不错的想法..

BR, INX

+0

这是完全可行的 - 一旦我在办公室落户,将发布一些代码给你。 – code4life

+0

谢谢,这将是非常好的:)! – Inx51

回答

0

docs

您可以使用统一的拦截作为一个独立的功能,没有通过使用Intercept类,依赖注入容器。

虽然语法很丑。

+0

是的..我有点希望尽可能简单..因为这就是为什么我想首先使用拦截的主要原因..这个想法是给几个添加一些新的值属性一旦他们被使用 – Inx51

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。

如果你绝对必须的,虽然绕过团结,这里是你如何做到这一点:

 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(); 
+0

谢谢:) ..然而..使用容器。解决方案来解决类型/接口这个想法是简单的一些如何告诉统一总是截取一个特定的类型,无论它创建使用解决(或任何DI)..或不..然而,我最终使用simulair方法,我猜.. – Inx51

+0

我会更新非Unity的方法。只是要警告,你必须手动设置治理,所以不是很直观,恕我直言。 – code4life

0

这是我落得这样做..

RegisterTypes在UnityConfig(MVC)

container.RegisterType<IDependencyResolverFactory, DependencyResolverFactory> 
       (
        new InjectionConstructor(container) 
       ); 
container.RegisterType<ISearchModel, SearchModel>(
       new Interceptor(typeof(VirtualMethodInterceptor)), 
       new InterceptionBehavior(typeof(SearchModelInterceptionBehaviour))); 

IDependencyResolverFactory

public interface IDependencyResolverFactory 
    { 
     TEntity Resolve<TEntity>(); 
    } 

DependencyResolverFactory 公共类DependencyResolverFactory:IDependencyResolverFactory { 私人IUnityContainer _container;

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()); 
    } 
} 

,然后简单地在我的控制器:

private IDependencyResolverFactory _dependencyResolverFactory; 

     public HomeController(IDependencyResolverFactory dependencyResolverFactory) 
     { 
      _dependencyResolverFactory = dependencyResolverFactory; 
     } 

public ActionResult Index() 
     { 
      var x = _dependencyResolverFactory.Resolve<SearchFormViewModel>(); 
      var p = x.Translations.Age; 
      var a = x.Translations.FirstName; 
      return View(); 
     } 

希望这使得scens的人除了我:P