微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将基类转换为派生的通用类型C#

如何解决将基类转换为派生的通用类型C#

我正在努力解决与泛型之间的转换有关的问题,这可能很容易。 基本上,我想创建一个基类列表并向其中添加多个类。

public interface IQueryEngineDependency
{
    public IEnumerable<QueryDependencyDetail> GetDependencies<>();
}

public abstract class QueryDependencyDetail
{
    public int Order { get; set; }
}

public class QueryDependencyDetail<TEntity,TKey> : QueryDependencyDetail
        where TEntity : BaseEntity<TKey>
{
    public virtual Func<TEntity,object> Key { get; set; }

    public IQueryable<TEntity> Data { get; set; }

    public Func<TEntity,object> JoinKey { get; set; }

    public Expression<Func<TEntity,bool>> WhereClause { get; set; }   
}

问题

例如,我有一个类可以实现上面显示的接口,但是我正在弄清楚实现该接口的正确方法

public class TestQueryDependency : IQueryEngineDependency
{
        public IEnumerable<QueryDependencyDetail> GetDependencies()
        {
            var dependencies = new List<QueryDependencyDetail>
            {
                new QueryDependencyDetail<Tasks,long>
                {
                    Order = 1,Data = null // just to simplify
                }
            };

            return dependencies;
        }
}

如果我在代码中的某处调用方法GetDependencies,如何进行向下转换以访问通用类型字段?我的意思是我将得到QueryDependencyDetail类型的实例。然后可以将其转换为QueryDependencyDetail<TEntity,TKey>吗? 还是有其他方法可以做到这一点?

编辑

var testDep = new TestQueryDependency();
var dependencies = testDep.GetDependencies();

请记住,在我的特定实现中,依赖项可能具有多达20个不同的实例。 例如,如何访问数据字段? (只是一个简单的场景)

var first = dependencies.FirstOrDefault()?.Data; ?????

我将需要它来使用LINQ执行动态查询

谢谢。

解决方法

您应该能够进行投射,即(QueryDependencyDetail<TEntity,TKey>) myObject

但是,您必须确保类型实际上与真实对象匹配。让我们举一个简化的例子:

    public class A { }
    public class B<T> : A { }
    public static B<T> Test<T>(A a) => (B<T>)a;

    var a = new B<int>();
    var b1 = Test<int>(a); // works since a is of type of B<int>
    var b2 = Test<string>(a); // Will throw invalid cast exception since a is not of type B<string>

您还可以测试类型:

if(a is B<int> b)

这里的问题是,您必须知道对象的实际类型。您不能仅将a强制转换为B<T>,而无需在某个地方声明T的实际含义。

我用于此类问题的解决方案是避免任何需要了解通用类型的事情。确保接口或基类包含与对象进行交互时所需的所有方法。当涉及多个类时,这可能会有些复杂,但通常是可能的。

编辑: 第三种选择是使用反射。这可以允许您检查泛型类型参数的实际类型。它可能允许诸如使用相同的泛型类型参数创建另一个对象之类的事情。缺点是使用反射可能很麻烦,并且容易出错且运行缓慢。

,

我不确定您要完成什么。

如果将通用参数放在引擎接口上怎么办?

public interface IQueryEngineDependency<TEntity,TKey> where TEntity : BaseEntity<TKey> {
    public IEnumerable<QueryDependencyDetail<TEntity,TKey>> GetDependencies();
}

然后您可以创建一个测试引擎:

public class TestQueryDependency : IQueryEngineDependency<Tasks,long> {
    public IEnumerable<QueryDependencyDetail<Tasks,long >> GetDependencies() {
        var dependencies = new[] {
                new QueryDependencyDetail<Tasks,long> {
                    Order = 1,Data = null // just to simplify
                }
            };

        return dependencies;
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。