C#类可以将自己的类型引用为泛型类型吗?

时间:2018-05-02 21:20:56

标签: c# generics inheritance

背景

我们在整个应用程序的几个地方使用构建器模式。 到目前为止,我们已经在我们的一些构建器中编写了以下方法,这些方法运行良好。

public class MyBuilderClass
{
    private MyConcreteType entity;

    public MyBuilderClass() { this.entity = new MyConcreteType(); }

    public MyBuilderClass With<TProperty>(Expression<Func<T, TProperty>> expressionToFindProperty, TProperty valueToSet)
    {
     MemberExpression member = (MemberExpression)expressionToFindProperty.Body;
                PropertyInfo property = (PropertyInfo)member.Member;
                property.SetValue(this.entity, valueToSet, null);
                return this;
    }
}

允许我们按照以下方式执行以下操作:

new MyBuilderClass().With(x=> x.MyProperty, "TheValue")

并且它推断出MyProperty在这种情况下是一个字符串。

目标

这很有用,所以我们希望能够以抽象的方式进行。有点像:

public abstract class AbstractBuilder<T, TBuilder> where TBuilder : AbstractBuilder<T, TBuilder>
{
    internal T entity;

    public TBuilder With<TProperty>(Expression<Func<T, TProperty>> expressionToFindProperty, TProperty valueToSet)
    {
        // Example usage: With(x => x.TrackingRecord, new TrackingRecord());
        MemberExpression member = (MemberExpression)expressionToFindProperty.Body;
        PropertyInfo property = (PropertyInfo)member.Member;
        property.SetValue(this.entity, valueToSet, null);
        return (TBuilder)this;
    }

    public T Build()
    {
        return this.entity;
    }
}

那么我们的混凝土建造者将遵循:

public class MyBuilderClass : AbstractBuilder<MyType, MyBuilderClass>
{
    // Code here
}

问题/问题

在上面的示例中,我们需要使用MyBuilderClass : AbstractBuilder<MyType, MyBuilderClass>,引用MyBuilderClass两次,以便我们的抽象构建器的TBuilder泛型类型正确运行。

在这种情况下,我们可以对AbstractBuilder进行更改,以便可以缩短子类的语法:

public class MyBuilderClass : AbstractBuilder<PaymentRecord, MyBuilderClass>

public class MyBuilderClass : AbstractBuilder<PaymentRecord>

其中TBuilder被推断为MyBuilderClass

我很想获得语法上的糖,而不必明确传递构建器的类型。

2 个答案:

答案 0 :(得分:4)

不,仿制药不喜欢做那样的事情。您需要传递类型参数。

总旁注;如果你经常建造这样的物体,反射会变得相当昂贵。

答案 1 :(得分:0)

可能会让catch函数返回with

例如:

AbstractBuilder<TType>

然后你可以进行所需的简单扩展:

public abstract class AbstractBuilder<T>
{
    internal T entity;

    public AbstractBuilder<T> With<TProperty>(Expression<Func<T, TProperty>> expressionToFindProperty, TProperty valueToSet)
    {
        // Example usage: With(x => x.TrackingRecord, new TrackingRecord());
        MemberExpression member = (MemberExpression)expressionToFindProperty.Body;
        PropertyInfo property = (PropertyInfo)member.Member;
        property.SetValue(this.entity, valueToSet, null);
        return this;
    }

    public T Build()
    {
        return this.entity;
    }
}

并称之为:

public class MyBuilderClass : AbstractBuilder<PaymentRecord>

缺点是,在调用var builder = new MyBuilderClass(); var record = builder .With(f => f.TrackingRecord, new MyTrackingRecord()) .Build(); 之后,它会将您的流畅api限制为抽象类,除非您重写函数调用以返回特定的构建器类型。