0

我正在寻找一种方法,一旦使用了特定类的属性,就总是拦截它的实例。

例如,如果 MyTestClass 将被拦截..这将触发拦截:

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

然后会拦截方法“get_SomeProperty”.. 但是我看到的所有使用 Unity 的示例都要求我通过 container.Resolve(); 来“管道”创建 MyTestClass 的实例;.. 我想避免这种情况。 . 有可能吗?.. 我很确定我以前曾经使用 Castle.DynamicProxy 做过类似的事情.. 但我当前的应用程序恰好安装了 Unity,所以重新使用 Unity 似乎是个好主意可能的。

不使用 container.Resolve() 的另一个原因是我的这个实例也可以在 MVC 操作中创建,它没有对容器的逻辑引用。我不认为将 MyTestClass 作为参数注入构造函数将是一个非常好的主意..

溴,英克斯

4

3 回答 3

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();
于 2015-10-02T14:34:24.497 回答
0

文档

通过使用 Intercept 类,您可以将 Unity 拦截作为独立功能使用,无需依赖注入容器。

虽然语法很丑。

于 2015-10-02T12:59:19.360 回答
0

这就是我最终做的..

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

希望这对除了我以外的人有影响:P

于 2015-10-02T15:05:43.083 回答