在Autofac中解析EF动态代理

Resolve EF dynamic proxy in Autofac

我正在使用 Entity Framework 并注册了一些类型用于工厂 class。

使用 Keyed 进行注册,如下所示:

builder.RegisterType<CreateTypeAStrategy>().Keyed<ICreateWorkItemsStrategy>(typeof(TypeA));

这里TypeA是一个实体。

我是这样解析的(action类型为TypeA):

var strategy = scope.ResolveKeyed<ICreateWorkItemsStrategy>(action.GetType(), new TypedParameter(action.GetType(), action));

我得到了预期的 ComponentNotRegisteredException,因为 proxy 没有注册,只有具体的 class 注册了。

接口和策略声明如下:

public interface ICreateWorkItemsStrategy
{
    IEnumerable<IWorkItem> CreateWorkItems();
}

public class CreateTypeAStrategy : ICreateWorkItemsStrategy
{
    public CreateTypeAStrategy(TypeA typeA)
    {

    }
    public IEnumerable<IWorkItem> CreateWorkItems()
    {
        throw new System.NotImplementedException();
    }
}

关于如何使用 EF 代理解决问题有什么建议吗?

完整的示例(需要 EF 和 Autofac nuget):

public class ApplicationDbContext : DbContext
{
    public virtual DbSet<TypeA> TypeAs { get; set; }
    public virtual DbSet<RefForProxy> Refs { get; set; }
}

public class RefForProxy
{
    public int Id { get; set; }
}

public class TypeA
{
    public int Id { get; set; }
    public virtual RefForProxy Ref { get; set; }
}

public interface ICreateWorkItemsStrategy
{
    IEnumerable<object> CreateWorkItems();
}

public class CreateTypeAStrategy : ICreateWorkItemsStrategy
{
    public CreateTypeAStrategy(TypeA typeA)
    {

    }
    public IEnumerable<object> CreateWorkItems()
    {
        throw new NotImplementedException();
    }
}

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        var builder = new ContainerBuilder();
        builder.RegisterType<CreateTypeAStrategy>().Keyed<ICreateWorkItemsStrategy>(typeof(TypeA));
        var container = builder.Build();

        int a_id;
        using (var ctx = new ApplicationDbContext())
        {

            var a = new TypeA { Ref = new RefForProxy() };
            ctx.TypeAs.Add(a);
            ctx.SaveChanges();
            a_id = a.Id;
        }

        using (var ctx = new ApplicationDbContext())
        {
            var aProxy = ctx.TypeAs.SingleOrDefault(x => x.Id == a_id);

            var strategy = container.ResolveKeyed<ICreateWorkItemsStrategy>(aProxy.GetType(), new TypedParameter(aProxy.GetType(), aProxy));
        }
    }
}

ObjectContext.GetObjectType 是您需要的方法。

Returns the entity type of the POCO entity associated with a proxy object of a specified type.

如果指定的类型不是代理而是 POCO 类型,它也是 return POCO 类型。

Type t = ObjectContext.GetObjectType(aProxy.GetType()); 
var strategy = container.ResolveKeyed<ICreateWorkItemsStrategy>(t, new TypedParameter(t, aProxy));