在父方法中返回子类型的通用方法

时间:2014-03-20 13:24:47

标签: c# generics extension-methods

我已经在C#中试验扩展方法几周了,我遇到了一些有趣的东西。我已经尝试过为我的DTO构建泛型:

public class ParentDto{
    public string attrStr{get;set;}
}

public static class ParentDtoExtensions{
    public static T AttrStr<T>(this T parentDto, string attrStr)
    where T:ParentDto{
        parentDto.attrStr = attrStr;
        return parentDto;
    }
}

然后在儿童班:

public class ChildDto:ParentDto{
    public string childAttrStr{get;set;}
}

public static class ChildDtoExtensions{
    public static T ChildAttrStr<T>(this T childDto, string childAttrStr)
    where T:ChildDto{
        childDto.childAttrStr = childAttrStr;
        return childDto;
    }
} 

然后让我链接我的方法:

return ((new ChildDto()).AttrStr("someString").ChildAttrStr("someOtherString"));

这真的很吸引我。能够拥有monad-ish setter以及其他方法返回调用类型非常方便链接一段代码。

然而我希望能够将setter方法集成到我认为真正属于的父类中,同时保持上面显示的现有代码流但我不知道一种方法来实现一个返回实现类的子类的方法。类似的东西:

public class ParentDto{
    public string attrStr{get;set;}

    public T AttrStr<T>(string attrStr)
    where T:ParentDto{
        parentDto.attrStr = attrStr;
        return parentDto;
    }
}

但是由于编译器(?)不知道调用类型,这不起作用。有谁知道怎么做?

请记住,我不是在寻找有关现有实施代码嗅觉的建议,因为我确信还有更多C# - 方法可以实现这一点。

2 个答案:

答案 0 :(得分:0)

您可以执行以下操作,但IMO您的扩展方法要好得多:

public class ParentDto<T> where T : ParentDto<T> {
    public string attrStr{get;set;}

    public T AttrStr(string attrStr) {
        this.attrStr = attrStr;
        return (T)this;
    }
}
public sealed class ChildDto : ParentDto<ChildDto> {
    public string childAttrStr{get;set;}
    public ChildDto ChildAttrStr(string childAttrStr) {
        this.childAttrStr = childAttrStr;
        return this;
    }
}

有关此模式的更多信息以及为何您应尽可能避免使用此模式,请参阅Eric Lippert's blog post, Curiouser and curiouser

那就是说,我同意这是代码气味;你应该只使用属性setter而不是流利的语法。但既然你不在那里寻求建议,我就把它留在那里。

答案 1 :(得分:0)

如果您正在做的就是在新对象上设置属性,那么您可以使用对象初始值设定项来执行此操作:

return new ChildDto()
    {
        attrStr = "someString",
        childAttrString = "someOtherString"
    }