【问题标题】:Is there a way to use a 'friendy' name for this class/interface?有没有办法为这个类/接口使用一个“友好”的名字?
【发布时间】:2018-05-18 05:51:50
【问题描述】:

基本上,我只是认为在我的项目中传递类型名称时很难看。我知道您不能使用实现该接口的接口,因为它是一个恰好实现原始接口的新接口,对吗?

public class GenericFactory<T, TTypeEnum> : IGenericFactory<T, TTypeEnum>
{
    private readonly IIndex<TTypeEnum, Func<CCompParms, T>> _factory;

    public GenericFactory(IIndex<TTypeEnum, Func<CCompParms, T>> factory)
    {
        _factory = factory;
    }

    public T Create(TTypeEnum serviceType, CCompParms comp)
    {
        return _factory[serviceType](comp);
    }
}

public interface IGenericFactory<T, TTypeEnum>
{
    T Create(TTypeEnum serviceType, CCompParms comp);
}

我试过了:

public interface FriendlyName : IGenericFactory<T, TTypeEnum>
{
}

但是当我尝试执行以下操作时,无论我如何施放它都无法施放。

IGenericFactory<T, TTypeEnum> inter = GetTheInterface();
FriendlyName fn = (inter as FriendlyName);

有没有办法让类型名称友好?

【问题讨论】:

  • 我认为您能做的最好的事情是using ALIAS = TYPE; 声明,但我建议您不要这样做,因为这样做并不常见,这样会使您的代码更难遵循。
  • 我也需要在每个班级都这样做,对吧?这是一个相当大的项目,我可以看到人们在复制代码时可能会感到困惑,突然之间他们在任何地方都找不到实际上是别名的“类型”。
  • 没错,这是另一个缺点。
  • @john 感谢您的建议,我会牢记这一点,并询问一些同行的想法。
  • 相关问题typedef in C#

标签: c# generics interface user-friendly


【解决方案1】:

首先,“友好名称”的任何通用解决方案仍然必须使用两种泛型类型进行参数化,所以我认为这不是您要寻找的,因为它不会真正为您节省任何输入.

假设您希望 FriendlyName 已经绑定了类型,那么 我认为您可以通过使用Implicit Conversions 和Decorator 模式找到一个可行的解决方案。

警告!!!我只是在浏览器中输入了这个(没有 IDE 或编译器),我的 C# 非常生锈,所以这可能需要调整

public interface FooFactory : IGenericFactory<Foo, FooEnum> {

    IGenericFactory<Foo, FooEnum> Wrapped { get; }

    // The "magic" - Note that magic always makes your code harder to understand...

    public static implicit operator FooFactory(IGenericFactory<Foo, FooEnum> wrapped) {
        // I think this can be placed here. If C# won't let you add this
        // implicit operator here, then you can easily implement this factory
        // method as an extension on IGenericFactory<Foo, FooEnum>
        return new FooFactoryWrapper(wrapped);
    }

    public static implicit operator IGenericFactory<Foo, FooEnum>(FooFactory wrapper) {
        return wrapper.Wrapped;
    }

    // I'm pretty sure we can hide this implementation here in the interface,
    // but again, my C# is pretty rusty, so you may have to move this
    // and/or change the visibility
    private class FooFactoryWrapper : FooFactory {

        public IGenericFactory<Foo, FooEnum> Wrapped { get; private set; }

        public FooFactoryWrapper(IGenericFactory<Foo, FooEnum> wrapped) {
            this.wrapped = wrapped;
        }

        // Since the "friendly type" is still an instance of the base type,
        // you'll still have to fully implement that interface. Just delegate
        // all calls to your wrapped type (most useless Decorator ever)

        public Foo Make() { return Wrapped.Make(); } // sample method in IGenericFactory<>
    }
}

现在,您应该可以像这样使用它:

IGenericFactory<Foo, FooEnum> inter = GetTheInterface();
FooFactory fn = inter; // implicit conversion to wrapper type

DoWork(fn); // use the "friendly name" like it were it's wrapped type
            // implicit conversion back to wrapped type

public void DoWork(IGenericFactory<Foo, FooEnum> fooFactory) {
    ...
}

话虽如此,我不会经历这种努力。每当我创建了这样的“友好名称”类型时,我都会将它们作为我的“模型”的一部分并将它们视为正确的类型,这意味着我直接在方法签名和构造函数中请求它们。

类似这样的:

public interface BarFactory : IGenericFactory<Bar, BarEnum> { }

// Asking for a BarFactory and not a IGenericFactory<Bar, BarEnum>
public void DoWork(BarFactory barFactory) { ... }

打字少了很多,也不需要魔法。

【讨论】:

  • 感谢您的详细回复,我会试一试。看起来很有希望!我真的不在乎人们是否不了解神奇的部分,我正在努力迎合初级开发人员,当他们看到泛型时,他们往往会失去注意力并挂在他们身上,并且不会真正关注其余部分的代码。我的一些开发人员最近才来自 VB6,所以对于他们不需要理解的东西,我能做的越多越好!一个完美的世界,我会让他们都接受更多的培训,但这不是一个选择。
  • 那不行,第一个问题是 C# 抛出接口不能包含操作符的错误:(
  • 将其更改为类也会引发有关在类和接口之间进行转换的错误。该死的。
  • Hmmm.... 你总是可以接受第二个建议,只在你的域中创建一个BarFactory,而不是传递一堆IGenericFactory&lt;Bar, BarEnum&gt;。我一直都是这样走的,而且效果似乎还不错。
  • 好的,感谢您抽出宝贵的时间,这就是我要做的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-22
  • 2020-09-23
  • 1970-01-01
  • 2018-07-07
  • 1970-01-01
  • 1970-01-01
  • 2012-04-07
相关资源
最近更新 更多