问题
Basically I just think the type name is ugly when passing it around my project. I know you can't use an interface that implements the interface because then it's a new interface that just happens to implement the original interface, right?
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);
}
I have tried:
public interface FriendlyName : IGenericFactory<T, TTypeEnum>
{
}
But when I try to do the following it fails to cast no matter how I cast it.
IGenericFactory<T, TTypeEnum> inter = GetTheInterface();
FriendlyName fn = (inter as FriendlyName);
Is there a way to make the type name friendly?
回答1:
First, any general solution for a "Friendly Name" will still have to be parameterized with both of the generic types, so I don't think that's what you're looking for since it won't really save you any typing.
Assuming you want FriendlyName
to already have the types bound, then
I think you can get to a workable solution by using Implicit Conversions and the Decorator pattern.
WARNING!!! I just typed this into the browser (no IDE or compiler) and my C# is very rusty, so this will likely need to be tweaked
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<>
}
}
Now, you should be able to use it like this:
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) {
...
}
All that being said, I wouldn't go through this effort. Whenever I've made "Friendly Name" types like this, I then make them part of my "model" and treat them as proper types, which means that I directly ask for them in method signatures and constructors.
Something like this:
public interface BarFactory : IGenericFactory<Bar, BarEnum> { }
// Asking for a BarFactory and not a IGenericFactory<Bar, BarEnum>
public void DoWork(BarFactory barFactory) { ... }
Much less typing and no need for magic.
来源:https://stackoverflow.com/questions/50404586/is-there-a-way-to-use-a-friendy-name-for-this-class-interface