在 C# 中,是否可以编写如下内容:
public class MyClass<T> : T
where T : class, new()
{
}
我知道上面的实现无法编译,但我实际上想要实现的是对未知类型实现某种通用包装器,以便客户端可以像调用类型一样调用包装器,由参数提供T
,而不是使用类似的东西来调用它wrapper.Instance.SomeMember()
。
提前致谢!
在 C# 中,是否可以编写如下内容:
public class MyClass<T> : T
where T : class, new()
{
}
我知道上面的实现无法编译,但我实际上想要实现的是对未知类型实现某种通用包装器,以便客户端可以像调用类型一样调用包装器,由参数提供T
,而不是使用类似的东西来调用它wrapper.Instance.SomeMember()
。
提前致谢!
这是不可能的。
在我看来,我认为不应该使用继承来实现包装器。
例如,假设我们有一个Engine
类,您需要实现一个FerrariEngine
. 你有一Car
堂课。
你是说Car
应该继承FerrariEngine
。这对我来说看起来很糟糕!
归根结底,您希望使用继承执行依赖注入之类的操作,而且这又不是正确的方法。
我的建议是不要试图让你的生活更轻松:根据理性点决定架构。
OP在一些评论中说:
我想让这个类来管理类型为 T 的对象的实例,这样客户端就不需要关心何时需要创建实例。
你不需要做奇怪的事情来得到你想要的:
public interface IEngine
{
void Start();
}
public sealed class FerrariEngine : IEngine
{
public FerrariEngine()
{
Start();
}
public void Start()
{
}
}
public abstract class Car<TEngine> where TEngine: IEngine, new()
{
public Car()
{
_engine = new Lazy<TEngine>(() => new TEngine());
}
private readonly Lazy<TEngine> _engine;
public TEngine Engine
{
get { return _engine.Value; }
}
}
public class FerrariCar : Car<FerrariEngine>
{
}
最后,如果我们创建一个实例FerrariCar
:
Car<FerrariEngine> myFerrari = new FerrariCar();
引擎将被实例化并启动,无需开发人员干预!
检查Lazy<T>
基本的通用约束是如何完成这项工作的;)
总之:
Lazy<T>
时,才会实例化使用引擎。Engine
FerrariEngine
实现了一个调用Start()
自身的无参数构造函数,它将启动引擎。我相信这个示例向您展示了如何获得所需的内容并“按原样”使用 C#!
您可以查看DynamicObject并执行以下操作:
class Foo<T> : DynamicObject
{
private T _instance;
public Foo(T instance)
{
_instance = instance;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
var member = typeof(T).GetProperty(binder.Name);
if (_instance != null &&
member.CanWrite &&
value.GetType() == member.PropertyType)
{
member.SetValue(_instance, value, null);
return true;
}
return false;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
var member = typeof(T).GetProperty(binder.Name);
if (_instance != null &&
member.CanRead)
{
result = member.GetValue(_instance, null);
return true;
}
result = null;
return false;
}
}
class Bar
{
public int SomeProperty { get; set; }
}
class Program
{
static void Main(string[] args)
{
var bar = new Bar();
dynamic thing = new Foo<Bar>(bar);
thing.SomeProperty = 42;
Console.WriteLine(thing.SomeProperty);
Console.ReadLine();
}
}