使用变量创建和对象,并将其传递给其他类
本文关键字:其他 变量 创建 对象 | 更新日期: 2023-09-27 18:26:20
我已经在代码示例中尽可能好地解释了它,我不确定我想要的是以某种方式实现的。
下面的代码确实有效,但我无法传递null
值,并且在创建"object"后也无法更改该值。我如何创建一个variableTable对象来实现这一点?
public static void SomeMethod(string variableOne, int variableTwo, UInt64 variableThree)
{
//create an object that contains variables for this specific method
//there are more methods like this 'SomeMethod' that have diferent variables and more or less variables
//this 'VariableHandler' reads and modifies the values via reflection and needs to be able to be used on onther methods
//also the variables can be null and this is not possible with an anonymous types
var variableTable = new { variableOne = variableOne, variableTwo = variableTwo, variableThree = variableThree }; //create an anomymous type with the variables
using (VariableHandler handler = new VariableHandler(variableTable)) //check and modify the variables via reflection
{
Console.WriteLine(variableTable.variableOne); //do somthing with the checked and modified methods
Console.WriteLine(variableTable.variableTwo);
Console.WriteLine(variableTable.variableThree);
}
}
也许你想为每个单独的变量使用一个小对象,比如:
public interface IVariableValue { }
public class VariableValue<T> : IVariableValue
{
public T Value { get; set; }
public VariableValue(T value) { Value = value; }
public override ToString() { return Value.ToString(); }
}
接口是必需的,因为您需要一些常用类型来存储在字典中。这是一个空白接口,因为如果不将接口设为泛型,我就无法定义T Value
属性,并且会遇到在同一字典中具有多个泛型类型的相同问题。
然后,使用Dictionary
:而不是匿名类型
public static void SomeMethod(string variableOne, int variableTwo, UInt64 variableThree)
{
var variableTable = new Dictionary<string, IVariableValue>()
{
["variableOne"] = new VariableValue<string>(variableOne),
["variableTwo"] = new VariableValue<int>(variableTwo),
["variableThree"] = new VariableValue<UInt64>(variableThree),
};
using (VariableHandler handler = new VariableHandler(variableTable))
{
Console.WriteLine(variableTable["variableOne"]);
Console.WriteLine(variableTable["variableTwo"]);
Console.WriteLine(variableTable["variableThree"]);
}
}
注意字典初始值设定项是C#6的一项功能,如果您不在C#上,则必须在创建字典后将其.Add
添加到字典中。
VariableHandler
可以在构造函数中取Dictionary<string, IVariableValue>
的参数:
public class VariableHandler : IDisposable
{
//IDisposable implementation not shown, but required for using
public VariableHandler(Dictionary<string, IVariableValue> variables)
{
//You can do whatever you want here using reflection
}
}
根据MSDN(此处),匿名类型的属性是只读的,因此您当然不能更改它们。它还声明不能将属性初始化为null。
为什么——你必须问微软,或者阅读这篇文章——可能会有更多适合你的东西。
如果您希望能够更改属性或将其初始化为null,则需要创建一个非匿名对象。
虽然Ron的答案满足了您的需要,但我认为它可以用一种不那么冗长的方式来解决。
如果参数名称不是特别重要,但能够将参数作为捆绑包传递、修改它们并使用它们再次调用方法,那么也许一个具有可写属性的类似Tuple
的类就足够了:
public static class Arguments
{
// This convenience method enables type-inference, so the generic types
// don't need to be supplied (which is necessary when calling the
// Arguments<T1, T2, T3> constructor):
public static Arguments<T1, T2, T3> Create<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3)
{
return new Arguments<T1, T2, T3>(arg1, arg2, arg3);
}
}
public class Arguments<T1, T2, T3>
{
public T1 Argument1 { get; set; }
public T2 Argument2 { get; set; }
public T3 Argument3 { get; set; }
public Arguments(T1 arg1, T2 arg2, T3 arg3)
{
Argument1 = arg1;
Argument2 = arg2;
Argument3 = arg3;
}
}
这可以如下使用:
public static void SomeMethod(string variableOne, int variableTwo, UInt64 variableThree)
{
var arguments = Arguments.Create(variableOne, variableTwo, variableThree);
Console.WriteLine(arguments.Argument1);
Console.WriteLine(arguments.Argument2);
Console.WriteLine(arguments.Argument3);
}
您必须为必须支持的每个数量的参数创建一个单独的类和方便方法,类似于不同数量的项有不同的Tuple
类。
参数名称
如果您确实需要保留参数名称,以便在不动态的情况下编写arguments.variableOne
,那么您必须为每个方法编写一个类。在这一点上,您还可以修改这些方法,以接受这样一个对象作为单个参数。
如果在运行时需要参数名称,可以使用反射来获取有关调用方法的信息。要可靠地做到这一点可能很棘手——正如Ron所指出的,strack跟踪检查或调用MethodBase.GetCurrentMethod
等几种方法在方法内联时都会失败。
但是,直接传递对该方法的引用应该有效:
public class Arguments
{
public static Arguments<T1, T2, T3> Create<T1, T2, T3>(Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3)
{
return new Arguments<T1, T2, T3>(action, arg1, arg2, arg3);
}
}
public class Arguments<T1, T2, T3>
{
public Argument<T1> Argument1 { get; set; }
public Argument<T2> Argument2 { get; set; }
public Argument<T3> Argument3 { get; set; }
public Arguments(Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3)
{
var methodInfo = action.GetMethodInfo();
var parameters = methodInfo.GetParameters();
Argument1 = new Argument<T1>(parameters[0].Name, arg1);
Argument2 = new Argument<T2>(parameters[1].Name, arg2);
Argument3 = new Argument<T3>(parameters[2].Name, arg3);
}
}
// A wrapper class to hold both the name and value of a parameter/argument:
public class Argument<T>
{
public string Name { get; private set; }
public T Value { get; set; }
public Argument(string name, T value)
{
Name = name;
Value = value;
}
}
用途更改为:
public static void SomeMethod(string variableOne, int variableTwo, UInt64 variableThree)
{
var arguments = Arguments.Create(SomeMethod, variableOne, variableTwo, variableThree).Dump();
Console.WriteLine(arguments.Argument1.Name + " = " + arguments.Argument1.Value);
Console.WriteLine(arguments.Argument2.Name + " = " + arguments.Argument2.Value);
Console.WriteLine(arguments.Argument3.Name + " = " + arguments.Argument3.Value);
}