C# 动态泛型实例

C# Dynamic generic instance

这是我的第一个问题,我对 C# 术语不是很熟悉,所以如果我混淆了一些术语或定义,我提前表示歉意。

我已经设置了一个通用的 EF 数据访问层;

public class BaseService<TObject> where TObject : class
{
    private DbContext Context;
    private static readonly Lazy<BaseService<TObject>> lazy = new Lazy<BaseService<TObject>>(() => new BaseService<TObject>());
    public static BaseService<TObject> Instance => lazy.Value;

    public BaseService()
    {
        Context = new evEntities();
    }

    public BaseService(DbContext context)
    {
        Context = context;
    }

    public ICollection<TObject> GetAll()
    {
        return Context.Set<TObject>().ToList();
    }

    public async Task<ICollection<TObject>> GetAllAsync()
    {
        return await Context.Set<TObject>().ToListAsync();
    }

    public TObject Get(int id)
    {
        return Context.Set<TObject>().Find(id);
    }
}

连同这个;

public static class DA
{
    public static DataAccess.Categories Categories => new DataAccess.Categories();
    public static DataAccess.Tags Tags => new DataAccess.Tags();
    public static DataAccess.Users Users => new DataAccess.Users();
}

public static class DA<T> where T : class
{
    public static BaseService<T> Base => new BaseService<T>();
}

所以在我的业务层我可以做到这一点;

public class Categories
{
    public Categories() { }

    public ICollection<Database.Categories> GetAll()
    {
        return DA.Categories.GetAll().ToList();
    }

    public async Task<ICollection<Database.Categories>> GetAllAsync()
    {
        return await DA.Categories.GetAllAsync();
    }

    public Database.Categories Get(int id)
    {
        return DA.Categories.Get(id);
    }
}

为清楚起见。我的 EF 创建了 classes/entities,比如 'Database.Categories' 和 'Database.Users',我将它们作为 'TObject' 传递给我的 BaseService,以获得拉取数据的标准方式来自我所有实体的数据库。

现在我的问题。我想以类似的方式创建一个通用的业务层。喜欢;

public class BusinessLogicBase<TModel>
{
    public ICollection<TDBModel> GetAll()
    {
        return null;
    }

    public async Task<ICollection<TDBModel>> GetAllAsync()
    {
        return await DA.Categories.GetAllAsync();
    }

    public TDBModel Get(int id)
    {
        return DA.Categories.Get(id);
    }
}

我希望能够使用类似 Database.Categories 的 TObject 调用 DA,但这必须是动态的,基于传递给 BusinessLogicBase 的类型。所以我想做这样的事情(这是行不通的);

private ???? DetermineDatabaseModel()
{
    switch(typeof(TModell))
    {
        case Models.Categories:
            return Database.Categories;
        case Models.Users:
            return Database.Users;
    }
}

所以我可以做到;

public ICollection<TDBModel> GetAll()
{
    var databaseModel = DetermineDatabaseModel()
    return DA<databaseModel>().GetAll();
}

希望你能理解我的问题并能帮助我。

谢谢!

抱歉拖了这么久 post,对于所有 9gaggers,这里有一个土豆...不是开玩笑,这是认真的。

你有没有尝试过类似的东西:

public class BusinessLogicBase<TDBModel> where TDBModel : class {
  public ICollection<TDBModel> GetAll() {
    return DA<TDBModel>.Base.GetAll();
  }
}

更新 1:

如果您先尝试在不使用泛型的情况下编写它,然后使用泛型将其转换为更通用的模式,也许会对您有所帮助。如果没有泛型,有些错误更容易解决。

方法 public ICollection<TDBModel> GetAll() 不能 return ICollection<TDBModel> 因为类型参数 TDBModel 未在 class 签名或方法签名中定义。如果你这样定义它更有意义:

public class BusinessLogicBase<TModel>
{
    public ICollection<TModel> GetAll()
    {
        return null;
    }
}

更新 2:

尝试 this simple console app 演示 dynamic 关键字并观察存储在变量 categoriesusers.

中的内容

更新 3:

基于 fiddle - 我已将 IBaseService<dynamic> 更改为 dynamic:

public class BL<TModel>
{
    // This is what i want to make dynamic.
    // how do i create a return type that i can use in DA<>..
    private Type testDetermineDatabaseModel()
    {
        switch(typeof(TModel).Name){
            case "Categories":
                return typeof(Database.Categories);
            case "Users":
                return typeof(Database.Users);
        }

        return null;
    }

    public ICollection<TModel> testGetAll() 
    {
        var databaseModel = testDetermineDatabaseModel();
        // return DA<databaseModel>().Base.GetAll();
        return new List<TModel>();
    }

    // NEW
    // I have constructed the following.
    private dynamic  baseService;

    public dynamic DetermineDatabaseModel()
    {
        switch (typeof(TModel).Name)
        {
            case "Categories":
                return new BaseService<Database.Categories>();
            case "Users":
                return new BaseService<Database.Users>();
            default:
                return null;
        }
    }

    private IBaseService<TDbModel> GetBase<TDbModel>() where TDbModel : class
    {
        return new BaseService<TDbModel>();
    }

    public ICollection<TModel> GetAll()
    {

        ICollection<TModel> returnValue = new List<TModel>();
        // This works!!!
        foreach (var item in GetBase<Database.Categories>().GetAll())
        {
            returnValue.Add((TModel)(object)item);
        }

        baseService = DetermineDatabaseModel();
        // This doesn't!!! It's the same thing!! :(
        foreach (var item in baseService.GetAll())
        {
            returnValue.Add((TModel)(object)item);
        }

        return returnValue;
    }
}

但请记住,这并不能解决您面临的问题。即 map 2 通用类型。