简体   繁体   English

通用静态缓存和协方差

[英]Generic static cache, and Covariance

I was trying to build a static generic cache which is going to hold method info of several methods of the form Apply(Event e). 我试图建立一个静态的通用缓存,它将保存Apply(Event e)形式的几种方法的方法信息。 A similar code is used in RedirectToWhen, from CQRS Lokad framework. CQRS Lokad框架在RedirectToWhen中使用了类似的代码。

The problem is that the generic cache doesn't consider derived classes if any. 问题是通用缓存不考虑派生类(如果有)。 This is a simple test that shows the undesired behavior: 这是一个显示不良行为的简单测试:

  [TestMethod]
    public void TestGenericsInheritance()
    {
        var sut = new DerivedFromAbstractType();
        Utils.UsefulMethod<DerivedFromAbstractType>(sut);
        Assert.AreEqual(10, sut.Value);
    }

    public abstract class AbstractType
{
    public int Value { get; set; }
}

public class DerivedFromAbstractType : AbstractType
{
    public void AnyOtherMethod()
    {
        Value = 10;
    }
}

public static class Utils
{
    public static void UsefulMethod<T>(T instance)
    {
        MethodInfo info = typeof(T)
            .GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
            .Where(m => m.Name == "AnyOtherMethod")
            .Where(m => m.GetParameters().Length == 0).FirstOrDefault();
        info.Invoke(instance,null);
     }
}

typeof(T) returns AbstractType, so I can't use it to build a generic static cache. typeof(T)返回AbstractType,所以我不能用它来构建通用的静态缓存。 How could I get a generic cache for methods awared of derived types? 我如何为知道派生类型的方法获取通用缓存?

use 采用

instance.GetType()

if instance is not null and typeof(T) os instance is null. 如果instance不为null并且typeof(T)os instance为null。

I know this is necro-ing a bit, but I had the same problem, with typeof(T) returning the base type. 我知道这有点坏处,但是我遇到了同样的问题,typeof(T)返回了基本类型。 This is useful when wanting to create a BaseAggregate which implements an Emit/Apply pattern. 当要创建实现发射/应用模式的BaseAggregate时,这很有用。 I solved it like this : 我这样解决了:

 private static class Cache
        {
            private static readonly IDictionary<Type, IDictionary<Type, MethodInfo>> _dict =
                new Dictionary<Type, IDictionary<Type, MethodInfo>>();

            public static IDictionary<Type, MethodInfo> GetDictionaryForType(Type type)
            {
                if (_dict.ContainsKey(type))
                {
                    return _dict[type];
                }
                var dict = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
                    .Where(m => m.Name == "When")
                    .Where(m => m.GetParameters().Length == 1)
                    .ToDictionary(m => m.GetParameters().First().ParameterType, m => m);
                _dict.Add(type, dict);
                return dict;
            }
        }

This still caches nicely, and object.GetType() returns the correct type to be fed into this method. 这仍然可以很好地缓存,并且object.GetType()返回正确的类型以馈入此方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM