Вы можете использовать методы расширения. Эта техника была названа псевдо-миксин .
Хотя методы расширения на самом деле являются статическими, они «притворяются» методами экземпляра, поэтому вам все еще нужен конкретный экземпляр T.
Кроме того, это своего рода обман, если вы хотите, чтобы ваш интерфейс сохранял свою роль в качестве самодокументируемого «контракта», который определяет, какие методы должен иметь ваш класс T.
Однако они безопасны по типу (ваш класс Foo не будет компилироваться, если вы не добавите IBarExtensions в область видимости)
//our interface
public interface IBar {}
// the two static methods are define as extension methods
public static class IBarExtensions {
public static string someMethod1(this IBar self) {
return "my initialization 1";
}
public static string someMethod2(this IBar self) {
return "my initialization 2";
}
}
public class Foo<T> where T : IBar, new()
{
public string value1 {get; private set;}
public string value2 {get; private set;}
public Foo() {
T t = new T(); // we can do this because of the "new()" constraint
// in the class definition
// Alternatively we could pass an instance of T in
// the constructor
// public Foo(T t)
value1 = t.someMethod1();
value2 = t.someMethod2();
}
}
тестирование
public class TestBar : IBar {}
void Main()
{
var c = new TestBar();
var t = new Foo<TestBar>();
Console.WriteLine(t.value1);
}