C # не безопасно поддерживает структурную типизацию (за исключением некоторых необычных контекстов), поэтому нет способа сделать это полностью безопасным без дублирования кода.Вы должны либо согласиться с техникой SLak, когда клиент запрашивает предоставить делегата (возможно, потребуется повторять одно и то же лямбда-выражение снова и снова), либо предположить , что базовые типы удовлетворятконтракт, содержащий метод public void DoSomething()
.
Переходя ко второму варианту, вот один из способов использования dynamic
в C # 4:
public class StructWrapper: AnInterface
{
private readonly dynamic m_struct;
public StructWrapper(object myStruct)
{
m_struct = myStruct;
}
public void DoSomething()
{
m_struct.DoSomething();
}
}
Теперь вы могли бы попытайтесь сделать этот класс универсальным, с типом базовой структуры, являющимся аргументом универсального типа, но это, вероятно, не сильно вам поможет, если вы также не захотите выполнить специфичную для структуры операций над упакованным типом.Вот пример этого с отражением и делегатами (совместим с C # 3):
public class StructWrapper<T> : AnInterface where T : struct
{
private readonly Action action;
// deliberately exposed
public T UnderlyingStruct { get; private set; }
public StructWrapper(T underlyingStruct)
{
UnderlyingStruct = underlyingStruct;
action = (Action)Delegate.CreateDelegate
(typeof(Action), underlyingStruct, "DoSomething");
}
public void DoSomething()
{
action();
}
}
Обратите внимание, что вы можете смешивать и сочетать два метода, упомянутых выше, например, отражение, но без обобщений.
Использование:
AnInterface wrapper1 = new StructWrapper(new Struct1());
wrapper1.DoSomething();
StructWrapper<Struct1> wrapper2 = new StructWrapper<Struct1>(new Struct1());
wrapper2.DoSomething();
Struct1 s = wrapper2.UnderlyingStruct; // generics help here
s.SomeOtherMethod();