在C#中是否可以创建扩展运算符?

7
所以基本的想法是:
我们有一些业务模型。
public class Model
{
    public int Foo { get; set; }
}

这是它的视图模型表示

public class ViewModel
{
    public string Foo { get; set; }

    public static explicit operator ViewModel(Model b)
    {
        // Map instances using AutoMapper or whatever
        return new ViewModel { Foo = b.Foo.ToString() };
    }
}

我们的基本本能是将模型映射到视图模型。正如你所看到的,我想使用explicit operator执行映射,这样我就可以进行以下操作:
var model = new Model { Foo = 42 }; // Get model
var viewModel = (ViewModel)model;   // Map to view model

我希望我的控制器代码尽可能地干净... 但是我想让视图模型和映射逻辑保持分离。如何将explicit operator的实现移动到某个外部类中?类似于扩展方法:

public static class Extensions
{
    public static explicit operator ViewModel(Model b)
    {
        // Map instances using Automapper or whatever
        return new ViewModel { Foo = b.Foo.ToString() };
    }
}

显然,此代码由于两个原因而无法编译:
- 静态类不能包含用户定义的运算符
- 参数或返回类型必须是 Extensions

此外,作为一种选择,我可以使视图模型部分化,并将模型本身和运算符分离到单独的 .cs 文件中,但这不会产生改变。在架构上,它们仍然是相同的类在同一个命名空间中。我希望能够在解决方案中的另一个项目中实现映射逻辑,例如。

我只想实现类似于扩展方法的效果。我该怎么做呢?


2
一个想法是:将您的ViewModel设置为部分类,然后在其中使用不同的文件来处理映射和模型本身。 - BitTickler
1
这将是一个可怕的编程体验。你能想象如果加法运算符的行为取决于你引用了哪些命名空间吗?太丑陋了! - Gusdor
@BitTickler,看到我的更新了吗...我已经考虑过那个选项了。 - Dmytro
@BitTickler 个人而言,我更喜欢有很多小的类,具有非常明确定义的行为。对于映射一个字符串来说,这可能不是合适的 - 我假设这只是一个更复杂问题的简单示例。 - Gusdor
@BitTickler,这里的问题不在于属性数量和映射过程本身(因为可以使用自动化工具如AutoMapper进行映射),而在于能否将映射逻辑放在ViewModel类之外但在explicit operator内部。我说得越多,听起来就越不可能。 - Dmytro
显示剩余4条评论
2个回答

5

没有比直接做更好的方法:

public class ModelToViewModelMapper
{
    public ViewModel Map(Model b)
    {
        return new ViewModel { Foo = b.Foo.ToString() };
    }
}

扩展方法可以完成相同的工作,但如果您想要更改映射逻辑,使用依赖注入和非静态类将会更容易。


1
如果将模型想象成有200个属性而不是1个,那么它看起来就不那么吸引人了,是吧? - BitTickler
@BitTickler 我看不到其他选择。你可以牺牲灵活性并发明一个适用于任何属性的通用机制,但值得这样做的情况太特殊了。 - astef
是的,这很好,谢谢你的帮助,这就是为什么我给你+1的原因,但是,正如我已经对BitTickler说的那样 - 这里的问题不在于映射过程本身,而在于能否将映射逻辑放在ViewModel类之外但在explicit operator内部。我越说它听起来越不可能。 - Dmytro
即使按照您所描述的方式可能是可行的,我仍建议不要这样做。显式转换只是静态方法周围的一种语法糖。它可以减少代码大小,但缺乏可扩展性。@DmytroTsiniavskyi - astef
@DmytroTsiniavskyi 为什么在讨论的两种情况下(运算符函数或命名函数)代码大小会有所不同?内部实现完全相同,对吧? - BitTickler
@BitTickler,他们确实会是这样。但我的问题更多地涉及扩展运算符而不是映射,这只是一个示例,作为使用扩展运算符的可能性之一。 - Dmytro

2

为什么不像 MSSystem.Linq 命名空间中那样做呢?有大量的类型转换是通过扩展方法完成的(你不能使用运算符,C# 不支持扩展运算符)。

定义以下扩展方法:

public static class Extensions
{    
    public static ViewModel ToViewModel(this Model model) {...}
}

我认为代码足够干净,这似乎是你在这里的主要目标。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接