从System.Type创建一个通用委托实例

时间:2012-12-27 12:14:15

标签: c# entity-framework generics reflection delegates

有没有办法让开放泛型类型参数的委托实例如此?

Action<T> SomethingHappened;

编译器给我一个错误。

我可能每两年就会问这个问题而忘了。我找不到以前的类似问题,所以无论如何我都要求了。

我真正想做的是:

在Entity Framework中,我希望无论何时向表中添加一些新行或者修改表的现有行中的某些数据,我都希望编写一个通用的发布者框架,可以告诉任何感兴趣的听众这样的等等。事情已经发生了。

例如发布商可以告知所有有兴趣知道客户表的新行添加或客户表中的任何修改的听众。

听众可能是记录器,电子邮件等。

目前,我正在做的是一个kludge,但我想要一个更安全的解决方案。这就是我目前正在做的事情:

 public partial class DaEntities : ObjectContext
    {
        Action<object, ObjectStateEntry> EntityModified;
        Action<object, ObjectStateEntry> EntityDeleted;
        Action<object, ObjectStateEntry> EntityAdded;

    public override int SaveChanges(SaveOptions options)
        {
            var modifiedEntities = 
                 ObjectStateManager.GetObjectStateEntries(
                 System.Data.EntityState.Added | System.Data.EntityState.Modified);

            var deletedEntities = 
                 ObjectStateManager.GetObjectStateEntries(
                 System.Data.EntityState.Deleted);

            foreach (var entry in modifiedEntities)
            {
                var type = GetObjectType(entry.GetType());

                // fire delegates here
            }

            return base.SaveChanges(options);
        }
    }

在上面的场景中,我更喜欢这样的事情:

public static Action<T, ObjectStateEntry> EntityModified;
public static Action<T, ObjectStateEntry> EntityDeleted;
public static Action<T, ObjectStateEntry> EntityAdded;

让他们指向像这样的通用方法:

public void SomethingHappenedToAnEntity<T, ObjectStateEntry>
    (T t, ObjectStateEntry e)
{
    // do stuff here
}

1 个答案:

答案 0 :(得分:0)

有一个未定义的'T'并没有任何意义...... - 你真正想要的是一个自定义事件参数。你必须在某些时候强制你的类型具体 - 所以,你可以传递参数,如:

Action<object> SomethingHappened;

然后让你的代码分支在消费方法中......

或者,你可以作弊,让动态调度尝试并为你找出类型(性能成本很低) - 但这只是推动了问题......

void Main()
{
    dynamic objectToProcess = new Moop();

    DoStuff(objectToProcess); //Dynamic dispatch will pick the best match automatically
}

public void DoStuff(Moop obj)
{
    Console.WriteLine(obj.GetType());
}

public void DoStuff(Gloop obj)
{
    Console.WriteLine(obj.GetType());
}

public void DoStuff(Bloop obj)
{
    Console.WriteLine(obj.GetType());
}

public class Moop {}
public class Gloop {}
public class Bloop {}