Нет, во многом потому, что эта модель довольно жесткая.Например, что, если вам нужен аргумент, который не будет установлен в поле;какой будет синтаксис для этого?Большинство решений, которые вы можете придумать, будут либо ограничивающими, либо почти столь же многословными, как и нынешний подход.
Тем не менее, в общем случае жесткость является проблемой только в общем случае.Если этот шаблон работает для вас, вы можете определить его с помощью наследования, которое является подходящим инструментом для этой работы.
Итак, вы можете определить набор общих Tuple<>
-подобных классов, которые вы можете наследовать от:
public abstract class TupleBase<T1>
{
public T1 Argument1 { get; private set; }
public TupleBase(T1 argument1)
{
this.Argument1 = argument1;
}
}
public abstract class TupleBase<T1, T2>
{
public T1 Argument1 { get; private set; }
public T2 Argument2 { get; private set; }
public TupleBase(T1 argument1, T2 argument2)
{
this.Argument1 = argument1;
this.Argument2 = argument2;
}
}
public abstract class TupleBase<T1, T2, T3>
{
public T1 Argument1 { get; private set; }
public T2 Argument2 { get; private set; }
public T3 Argument3 { get; private set; }
public TupleBase(T1 argument1, T2 argument2, T3 argument3)
{
this.Argument1 = argument1;
this.Argument2 = argument2;
this.Argument3 = argument3;
}
}
// Etc..
Тогда
class MyClass
{
int var1;
int var2;
int var3;
int var4;
public MyClass(int var1, int var2, int var3, int var4){
this.var1 = var1;
this.var2 = var2;
this.var3 = var3;
this.var4 = var4;
}
}
становится
class MyClass : TupleBase<int, int, int, int>
{
public MyClass(int var1, int var2, int var3, int var4)
: base(var1, var2, var3, var4)
{
}
}
.
Наследование является фундаментально правильным инструментом для этого, поскольку вы хотите MyClass
подобрать по базовому шаблону, т.е. наследовать его.Проблема, с которой вы столкнетесь в C #, заключается в том, что вы можете наследовать только от одного класса за раз, поэтому вы не можете просто использовать дополнительные функции, подобные этой, во всех случаях.
В качестве альтернативы вы можете написать
class MyClass
{
int var1;
int var2;
int var3;
int var4;
public MyClass(int var1, int var2, int var3, int var4){
this.SetConstructorValues(var1, var2, var3, var4);
}
}
, где .SetConstructorValues()
- это общий метод расширения
private static System.Collections.ConcurrentDictionary<Type, Action<object, object[]>> ConstructorSetterDictionary { get; private set; }
public static void SetConstructorValues<T_SetClass>(
this T_SetClass instanceToSetValuesFor
, params object[] constructorArguments
)
{
var instanceType = typeof(T_SetClass);
Action<object, object[]> constructorSetterAction;
if (!ConstructorSetterDictionary.TryGetValue(
instanceType
, out constructorSetterAction
))
{
throw new Exception("Populate the dictionary! Also change this Exception message; it's from a StackOverflow example and not really designed to actually be written like this.");
}
constructorSetterAction(
instanceToSetValuesFor
, constructorArguments
);
}
, где ConstructorSetterDictionary
- словарь установщика - Action<object, object[]>
для каждого Type
выводится в соответствии с любой логикой, которая вам нравится (например, сопоставление конструкторов с именами параметров для полей), заполняется при запуске программы с использованием отражения.
Концептуально, получение метода, подобного этому, основанного на Type
объекта, в основном заключается в том, какработают виртуальные методы, где ConstructorSetterDictionary
- это виртуальная таблица поиска.
Я считаю, что такого рода метапрограммирование полезно в моей собственной работе, но предупреждаю, что в какой-то момент он перестает быть C #.