使用 ExtraalInterface() 注入接口时,Unity 抛出 NotImplementException "Additional interfaces do not have an imp



我正在尝试使用Unity在不接触现有代码库的情况下在对象顶部添加接口。

这里的目标是通过在我的应用程序中简单地配置现有的代码库,将一些拦截器应用于现有的代码基。

需要牢记的事项:

  • 我知道我可以将接口应用于所有必要的类。我只是想知道是否有可能在运行时使用我的Unity配置来应用所有这些,而不是修改所有现有的代码
  • 在这种特殊情况下,拦截器实际上只是一个直通,我希望生成的虚拟代理具有我的IWhatever接口所需的必要属性
  • 我提供的代码抛出了一个NotImplementedException,但据我所知,"Name"属性应该已经注入到代理中

这里有一个代码示例:

public class Program
{
    public static void Main(string[] args)
    {
        IUnityContainer container = new UnityContainer()
            .AddNewExtension<Interception>();
        container.RegisterType<ICat, Cat>(
            new InjectionMember[]
                {
                    new AdditionalInterface<IWhatever>(),
                    new InjectionProperty("Name",""),           //checking to see if this will fix our IWhatever injection problem
                    new Interceptor<VirtualMethodInterceptor>(),
                    new InterceptionBehavior<VirPropInterceptorBehavior>()
                }
        );
        ICat c = container.Resolve<ICat>();
        string propVal = ((IWhatever)c).Name;

        Console.Read();
    }
}
public interface IWhatever
{
    void DoWhatever();
    string Name { get; set; }
}
public interface ICat
{
}
public class Cat : IAuditable, ICat
{
    public int Age { get; set; }
    public string Name { get; set; }
}
public class VirPropInterceptorBehavior : IInterceptionBehavior
{
    private object propVal;
    public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
    {
        return getNext()(input, getNext);
    }
    public IEnumerable<Type> GetRequiredInterfaces()
    {
        return new[] { typeof(IWhatever) };
    }
    public bool WillExecute
    {
        get { return false; }
    }
}

您有两个问题。首先,Cat没有提供IWhatever的实现——尽管它有Name,但这不是IWhateverName的实现。在Cat上找不到它。你可以这样做,但注意它终止了拦截器链:

    public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
    {
        if (input.MethodBase.DeclaringType == typeof (IWhatever)
            && input.MethodBase.Name == "get_Name")
        {
            return input.CreateMethodReturn(((Cat) (input.Target)).Name);
        }
        return getNext()(input, getNext);
    }

也许您想将Name存储在Cat对象之外的其他地方——也许是在针对对象实例的Dictionary中(想想DependencyProperty系统在WPF中是如何工作的)。

第二个问题是…你会踢自己。。。您需要WillExecute返回true才能运行拦截器。

实际上,您必须在您的行为VirPropInterceptorBehavior中编写IWhatever's Name的实现。请参阅https://unity.codeplex.com/discussions/227719详细信息。

但问题仍然存在,如何处理这种情况?在您的行为中,您必须识别对IWhatever.Name的调用,并在那里实现它(在行为的Invoke方法中)。你可以这样做。我只为GET实现了,您可以为setter实现。

public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
    {
        IMethodReturn result;
        // Taking care of implementation of additional interface IWhatever.
        if (input.MethodBase.DeclaringType == typeof (IWhatever))
        {
            switch (input.MethodBase.Name)
            {
                case "get_Name":
                    // Do your stuff here
                    // Make sure you do this to get rid of your exception.
                    // Pass the argument so that the calling code gets it.
                    result = input.CreateMethodReturn(input.Arguments[0]);
                    break;
                default:
                    result = input.CreateMethodReturn(null);
                    break;
            }
        }
        else
        {
            // Do other stuff here.
            result = getNext()(input, getNext);
        }
        return result;
    }

我希望它能帮助你。

相关内容

最新更新