extending/shrinking 数组范围的简化方法(鸭子打字
Simplify Method for extending/shrinking range of arrays (duck typing
我正在尝试简化一种向一系列数组添加额外条目的方法。这是当前脚本:
private static void AddEntryToSettingsArrays()
{
string[] Temparray1 = GlobalVariables.Array1; // Copys the setting array "1" to a temporary array.
int[] Temparray2 = GlobalVariables.Array2; // Copys the setting array "2" to a temporary array.
//...
GlobalVariables.ArrayCount++; // Increments the Array count by one.
GlobalVariables.Array1 = new string[GlobalVariables.ArrayCount]; // Clears array "1" and creates a new array with the new array count.
GlobalVariables.Array2 = new int[GlobalVariables.ArrayCount]; // Clears array "2" and creates a new array with the new array count.
//...
for (int ArrayID = 0; ArrayID < GlobalVariables.ArrayCount - 1; ArrayID++) //Loops through the arrays until the next to last array is reached.
{
GlobalVariables.Array1[ArrayID] = Temparray1[ArrayID]; // Copys the "1" temporary array back to the global array.
GlobalVariables.Array2[ArrayID] = Temparray2[ArrayID]; // Copys the "2" temporary array back to the global array.
//...
}
}
根据数组的范围,此方法变得越来越...庞大且难以管理。
为了简化函数,我创建了一个可能数组的字典:
private static BatchArraysDictionary CreateBatchArrayDictionary()
{
BatchArraysDictionary PossibleBatchArrays = new BatchArraysDictionary(); // Creates a new "Batch Array Dictionary".
PossibleBatchArrays.Add(nameof(GlobalVariables.Array1), GlobalVariables.Array1.GetType());
PossibleBatchArrays.Add(nameof(GlobalVariables.Array2), GlobalVariables.Array2.GetType());
//...
return PossibleBatchArrays;
}
现在我正在尝试使用该词典来简化该功能:
private static void AddEntryToSettingsArrays()
{
BatchArraysDictionary CurrentArrays = CreateBatchArrayDictionary();
GlobalVariables.ArrayCount++; // Increments the folder count by one.
foreach (KeyValuePair<string, Type> CurrentArray in CurrentArrays)
{
Type CurrentType = CurrentArray.Value;
var TempArray = typeof(GlobalVariables).GetField(CurrentArray.Key).GetValue(CurrentType);
var GlobalArray = new CurrentType[GlobalVariables.ArrayCount]; // Getting the is a 'Type' but is used like a 'Variable' Error here...
for(int ArrayID = 0; ArrayID < GlobalVariables.ArrayCount - 1; ArrayID++) //Loops through the Folders until the next to last folder is reached.
{
// Not sure what to do here jet (What's the equivalent to "GlobalVariables.Array1[ArrayID] = Temparray1[ArrayID];")
}
}
但我在第 10 行收到 "is a 'Type' but is used like a 'Variable'" 错误。
此外,我不知道如何设置全局变量,如:
GlobalVariables.Array1[ArrayID] = Temparray1[ArrayID];
也许你们中有人可以帮助我解决我的问题。
---------------- 2016-05-11 更新:
我已尝试改进我的方法,但我知道我遇到了无效转换异常或访问冲突。 (取决于变量的类型)
private static void AddEntryToSettingsArrays()
{
BatchArraysDictionary CurrentArrays = CreateBatchArrayDictionary();
GlobalVariables.FolderCount++; // Increments the folder count by one.
foreach (KeyValuePair<string, Type> CurrentArray in CurrentArrays)
{
Type ArrayType = CurrentArray.Value;
//Console.WriteLine("Array Type (Stored): " + ArrayType);
FieldInfo TempArrayField = typeof(GlobalVariables).GetField(CurrentArray.Key);
//Console.WriteLine("Array Type (Field): " + TempArrayField.GetValue(typeof(GlobalVariables)));
dynamic[] TempSourceArray = (dynamic[])TempArrayField.GetValue(typeof(GlobalVariables));
//Console.WriteLine("Array loaded.");
dynamic[] TempDestinationArray = new dynamic[GlobalVariables.FolderCount];
//Console.WriteLine("New Array created.");
for (int ArrayID = 0; ArrayID < GlobalVariables.FolderCount - 1; ArrayID++) //Loops through the Folders until the next to last folder is reached.
{
TempDestinationArray[ArrayID] = TempSourceArray[ArrayID];
//Console.WriteLine("Array ID " + ArrayID + " was copied to new array");
}
//Console.WriteLine("Copyprccess finished.");
//Console.WriteLine("Testentry:" + TempDestinationArray[0]);
TempArrayField.SetValue(typeof(GlobalVariables), Convert.ChangeType(TempDestinationArray, ArrayType));
}
}
我尝试将当前数组转换为动态变量,但在最后一行设置了新值...
TempArrayField.SetValue(typeof(GlobalVariables), Convert.ChangeType(TempDestinationArray, ArrayType));
...因无效转换异常而失败。
此外,如果数组是 int[] 或 bool[] 类型,它已经在行失败...
dynamic[] TempSourceArray = (dynamic[])TempArrayField.GetValue(typeof(GlobalVariables));
"Access violation".
也许我现在说清楚了我要实现的目标。
对于所有好奇的人,我找到了解决问题的方法。
这是我想出的:
首先,我将数组字典更改为列表,因为现在只需要名称:
/// <summary>
/// Class that contain the names of arrays used to save settings.
/// </summary>
private class ArrayNamesList : List<string>
{
/// <summary>
/// Adds an array name to the list.
/// </summary>
/// <param name="GlobalVariableName">Name of the array variable.</param>
internal new void Add(string GlobalVariableName)
{
base.Add(GlobalVariableName);
}
}
在这个方法中的用法:
/// <summary>
/// Method that creates a list of possible batch setting array names.
/// </summary>
/// <returns>Returns a list of possible batch setting array names.</returns>
private static ArrayNamesList CreateArrayDictionary()
{
BatchArrayNamesList PossibleBatchArrays = new BatchArrayNamesList(); // Creates a new "Batch Array Names List".
PossibleBatchArrays.Add(nameof(GlobalVariables.ArrayOne)); // Adds the setting "1" name to the List.
PossibleBatchArrays.Add(nameof(GlobalVariables.ArrayTwo)); // Adds the setting "2" name to the List.
// ...
return PossibleBatchArrays;
}
然后我创建了两个函数来扩展数组和从数组中删除条目:
延长:
/// <summary>
/// Function that increases an array of unknown type to a certain length.
/// </summary>
/// <param name="CurrentArray">The array that needs to be increased in size.</param>
/// <param name="NewArraySize">The new size of the array.</param>
private static void ArrayResize(ref Array CurrentArray, int NewArraySize)
{
if (CurrentArray.Length < NewArraySize) // Checks if the new array size is larger than the old size.
{
Type elementType = CurrentArray.GetType().GetElementType(); // Gets the type of the arrays elements.
Array newArray = Array.CreateInstance(elementType, NewArraySize); // Creats a new array with the new length.
Array.Copy(CurrentArray, newArray, CurrentArray.Length); // Transfers the data from the old array to the new array.
CurrentArray = newArray; // Replaces the old array with the new array.
}
else
{
Debugging.ErrorHandling.ErrorHandler("The new array size is not larger than the old array size.", 1201); // Creates an event log entry and error messagebox if application is run with gui.
}
}
在这个方法中的用法:
/// <summary>
/// Method that adds a new empty entry to all setting arrays.
/// </summary>
private static void AddEntryToSettingsArrays()
{
ArrayNamesList CurrentArrays = CreateArrayDictionary(); // Creates a list of the currently used setting arrays.
GlobalVariables.FolderCount++; // Increments the folder count by one.
foreach (string CurrentArray in CurrentArrays) // Loops through the list of arrays.
{
FieldInfo TempArrayField = typeof(GlobalVariables).GetField(CurrentArray); // Gets the current array with reflection.
Array TempArray = (Array)TempArrayField.GetValue(typeof(GlobalVariables)); // Gets value of the current array.
ArrayResize(ref TempArray, GlobalVariables.FolderCount); // Resizes the array.
Type ArrayType = TempArray.GetType().GetElementType(); // Gets the type of the array.
TempArrayField.SetValue(ArrayType, TempArray); // Replaces the old with the new array.
}
}
删除条目:
/// <summary>
/// Function that removes an entry from an array of unknown type.
/// </summary>
/// <param name="CurrentArray">The array an entry needs to be deleted from.</param>
/// <param name="NewArraySize">The new size of the array.</param>
/// <param name="RemoveArrayID">The ID of the arrays entry that needs to be removed.</param>
private static void ArrayResize(ref Array CurrentArray, int NewArraySize, int RemoveArrayID)
{
if
(
NewArraySize <= 0 // Checks if the new array size is not negative.
&& (CurrentArray.Length - 1) == NewArraySize // And if the new array size is the same than the old array size minus one entry.
)
{
Type elementType = CurrentArray.GetType().GetElementType(); // Gets the type of the arrays elements.
Array newArray = Array.CreateInstance(elementType, NewArraySize); // Creats a new array with the new length.
if (NewArraySize != 0) // if the new array is not empty.
{
int PositionStart = RemoveArrayID + 1; // Calculates the the start position of the entrys behind the removed ID.
int RemainingLength = newArray.Length - RemoveArrayID; // Calculates the length of the array behind the removed ID.
if (RemoveArrayID > 0) // If the array ID that should be remove is not the first entry.
{
Array.Copy(CurrentArray, 0, newArray, 0, RemoveArrayID); // Copys the entrys in front of the removed ID in the new array.
}
else if (RemainingLength > 0) // If the array ID that should be remove is not the last entry.
{
Array.Copy(CurrentArray, PositionStart, newArray, RemoveArrayID, RemainingLength); // Copys the entrys behind the removed ID in the new array.
}
}
CurrentArray = newArray; // Replaces the old array with the new array.
}
else
{
Debugging.ErrorHandling.ErrorHandler("The new array size has an negative value or is not one entry smaller that the old array size.", 1202); // Creates an event log entry and error messagebox if application is run with gui.
}
}
在这个方法中的用法:
/// <summary>
/// Method that removes a certain entry from all setting arrays.
/// </summary>
/// <param name="RemoveID">ID of the setting that should be removed from the settings.</param>
private static void RemoveEntryFromSettingsArrays(int RemoveID)
{
ArrayNamesList CurrentArrays = CreateArrayDictionary(); // Creates a list of the currently used setting arrays.
GlobalVariables.FolderCount--; // Decrements the folder count by one.
foreach (string CurrentArray in CurrentArrays) // Loops through the list of arrays.
{
FieldInfo TempArrayField = typeof(GlobalVariables).GetField(CurrentArray);// Gets the current array with reflection.
Array TempArray = (Array)TempArrayField.GetValue(typeof(GlobalVariables)); // Gets value of the current array.
ArrayResize(ref TempArray, GlobalVariables.FolderCount, RemoveID); // Removes an ID from the array.
Type ArrayType = TempArray.GetType().GetElementType(); // Gets the type of the array.
TempArrayField.SetValue(ArrayType, TempArray); // Replaces the old with the new array.
}
}
我正在尝试简化一种向一系列数组添加额外条目的方法。这是当前脚本:
private static void AddEntryToSettingsArrays()
{
string[] Temparray1 = GlobalVariables.Array1; // Copys the setting array "1" to a temporary array.
int[] Temparray2 = GlobalVariables.Array2; // Copys the setting array "2" to a temporary array.
//...
GlobalVariables.ArrayCount++; // Increments the Array count by one.
GlobalVariables.Array1 = new string[GlobalVariables.ArrayCount]; // Clears array "1" and creates a new array with the new array count.
GlobalVariables.Array2 = new int[GlobalVariables.ArrayCount]; // Clears array "2" and creates a new array with the new array count.
//...
for (int ArrayID = 0; ArrayID < GlobalVariables.ArrayCount - 1; ArrayID++) //Loops through the arrays until the next to last array is reached.
{
GlobalVariables.Array1[ArrayID] = Temparray1[ArrayID]; // Copys the "1" temporary array back to the global array.
GlobalVariables.Array2[ArrayID] = Temparray2[ArrayID]; // Copys the "2" temporary array back to the global array.
//...
}
}
根据数组的范围,此方法变得越来越...庞大且难以管理。
为了简化函数,我创建了一个可能数组的字典:
private static BatchArraysDictionary CreateBatchArrayDictionary()
{
BatchArraysDictionary PossibleBatchArrays = new BatchArraysDictionary(); // Creates a new "Batch Array Dictionary".
PossibleBatchArrays.Add(nameof(GlobalVariables.Array1), GlobalVariables.Array1.GetType());
PossibleBatchArrays.Add(nameof(GlobalVariables.Array2), GlobalVariables.Array2.GetType());
//...
return PossibleBatchArrays;
}
现在我正在尝试使用该词典来简化该功能:
private static void AddEntryToSettingsArrays()
{
BatchArraysDictionary CurrentArrays = CreateBatchArrayDictionary();
GlobalVariables.ArrayCount++; // Increments the folder count by one.
foreach (KeyValuePair<string, Type> CurrentArray in CurrentArrays)
{
Type CurrentType = CurrentArray.Value;
var TempArray = typeof(GlobalVariables).GetField(CurrentArray.Key).GetValue(CurrentType);
var GlobalArray = new CurrentType[GlobalVariables.ArrayCount]; // Getting the is a 'Type' but is used like a 'Variable' Error here...
for(int ArrayID = 0; ArrayID < GlobalVariables.ArrayCount - 1; ArrayID++) //Loops through the Folders until the next to last folder is reached.
{
// Not sure what to do here jet (What's the equivalent to "GlobalVariables.Array1[ArrayID] = Temparray1[ArrayID];")
}
}
但我在第 10 行收到 "is a 'Type' but is used like a 'Variable'" 错误。 此外,我不知道如何设置全局变量,如:
GlobalVariables.Array1[ArrayID] = Temparray1[ArrayID];
也许你们中有人可以帮助我解决我的问题。
---------------- 2016-05-11 更新:
我已尝试改进我的方法,但我知道我遇到了无效转换异常或访问冲突。 (取决于变量的类型)
private static void AddEntryToSettingsArrays()
{
BatchArraysDictionary CurrentArrays = CreateBatchArrayDictionary();
GlobalVariables.FolderCount++; // Increments the folder count by one.
foreach (KeyValuePair<string, Type> CurrentArray in CurrentArrays)
{
Type ArrayType = CurrentArray.Value;
//Console.WriteLine("Array Type (Stored): " + ArrayType);
FieldInfo TempArrayField = typeof(GlobalVariables).GetField(CurrentArray.Key);
//Console.WriteLine("Array Type (Field): " + TempArrayField.GetValue(typeof(GlobalVariables)));
dynamic[] TempSourceArray = (dynamic[])TempArrayField.GetValue(typeof(GlobalVariables));
//Console.WriteLine("Array loaded.");
dynamic[] TempDestinationArray = new dynamic[GlobalVariables.FolderCount];
//Console.WriteLine("New Array created.");
for (int ArrayID = 0; ArrayID < GlobalVariables.FolderCount - 1; ArrayID++) //Loops through the Folders until the next to last folder is reached.
{
TempDestinationArray[ArrayID] = TempSourceArray[ArrayID];
//Console.WriteLine("Array ID " + ArrayID + " was copied to new array");
}
//Console.WriteLine("Copyprccess finished.");
//Console.WriteLine("Testentry:" + TempDestinationArray[0]);
TempArrayField.SetValue(typeof(GlobalVariables), Convert.ChangeType(TempDestinationArray, ArrayType));
}
}
我尝试将当前数组转换为动态变量,但在最后一行设置了新值...
TempArrayField.SetValue(typeof(GlobalVariables), Convert.ChangeType(TempDestinationArray, ArrayType));
...因无效转换异常而失败。
此外,如果数组是 int[] 或 bool[] 类型,它已经在行失败...
dynamic[] TempSourceArray = (dynamic[])TempArrayField.GetValue(typeof(GlobalVariables));
"Access violation".
也许我现在说清楚了我要实现的目标。
对于所有好奇的人,我找到了解决问题的方法。
这是我想出的:
首先,我将数组字典更改为列表,因为现在只需要名称:
/// <summary>
/// Class that contain the names of arrays used to save settings.
/// </summary>
private class ArrayNamesList : List<string>
{
/// <summary>
/// Adds an array name to the list.
/// </summary>
/// <param name="GlobalVariableName">Name of the array variable.</param>
internal new void Add(string GlobalVariableName)
{
base.Add(GlobalVariableName);
}
}
在这个方法中的用法:
/// <summary>
/// Method that creates a list of possible batch setting array names.
/// </summary>
/// <returns>Returns a list of possible batch setting array names.</returns>
private static ArrayNamesList CreateArrayDictionary()
{
BatchArrayNamesList PossibleBatchArrays = new BatchArrayNamesList(); // Creates a new "Batch Array Names List".
PossibleBatchArrays.Add(nameof(GlobalVariables.ArrayOne)); // Adds the setting "1" name to the List.
PossibleBatchArrays.Add(nameof(GlobalVariables.ArrayTwo)); // Adds the setting "2" name to the List.
// ...
return PossibleBatchArrays;
}
然后我创建了两个函数来扩展数组和从数组中删除条目:
延长:
/// <summary>
/// Function that increases an array of unknown type to a certain length.
/// </summary>
/// <param name="CurrentArray">The array that needs to be increased in size.</param>
/// <param name="NewArraySize">The new size of the array.</param>
private static void ArrayResize(ref Array CurrentArray, int NewArraySize)
{
if (CurrentArray.Length < NewArraySize) // Checks if the new array size is larger than the old size.
{
Type elementType = CurrentArray.GetType().GetElementType(); // Gets the type of the arrays elements.
Array newArray = Array.CreateInstance(elementType, NewArraySize); // Creats a new array with the new length.
Array.Copy(CurrentArray, newArray, CurrentArray.Length); // Transfers the data from the old array to the new array.
CurrentArray = newArray; // Replaces the old array with the new array.
}
else
{
Debugging.ErrorHandling.ErrorHandler("The new array size is not larger than the old array size.", 1201); // Creates an event log entry and error messagebox if application is run with gui.
}
}
在这个方法中的用法:
/// <summary>
/// Method that adds a new empty entry to all setting arrays.
/// </summary>
private static void AddEntryToSettingsArrays()
{
ArrayNamesList CurrentArrays = CreateArrayDictionary(); // Creates a list of the currently used setting arrays.
GlobalVariables.FolderCount++; // Increments the folder count by one.
foreach (string CurrentArray in CurrentArrays) // Loops through the list of arrays.
{
FieldInfo TempArrayField = typeof(GlobalVariables).GetField(CurrentArray); // Gets the current array with reflection.
Array TempArray = (Array)TempArrayField.GetValue(typeof(GlobalVariables)); // Gets value of the current array.
ArrayResize(ref TempArray, GlobalVariables.FolderCount); // Resizes the array.
Type ArrayType = TempArray.GetType().GetElementType(); // Gets the type of the array.
TempArrayField.SetValue(ArrayType, TempArray); // Replaces the old with the new array.
}
}
删除条目:
/// <summary>
/// Function that removes an entry from an array of unknown type.
/// </summary>
/// <param name="CurrentArray">The array an entry needs to be deleted from.</param>
/// <param name="NewArraySize">The new size of the array.</param>
/// <param name="RemoveArrayID">The ID of the arrays entry that needs to be removed.</param>
private static void ArrayResize(ref Array CurrentArray, int NewArraySize, int RemoveArrayID)
{
if
(
NewArraySize <= 0 // Checks if the new array size is not negative.
&& (CurrentArray.Length - 1) == NewArraySize // And if the new array size is the same than the old array size minus one entry.
)
{
Type elementType = CurrentArray.GetType().GetElementType(); // Gets the type of the arrays elements.
Array newArray = Array.CreateInstance(elementType, NewArraySize); // Creats a new array with the new length.
if (NewArraySize != 0) // if the new array is not empty.
{
int PositionStart = RemoveArrayID + 1; // Calculates the the start position of the entrys behind the removed ID.
int RemainingLength = newArray.Length - RemoveArrayID; // Calculates the length of the array behind the removed ID.
if (RemoveArrayID > 0) // If the array ID that should be remove is not the first entry.
{
Array.Copy(CurrentArray, 0, newArray, 0, RemoveArrayID); // Copys the entrys in front of the removed ID in the new array.
}
else if (RemainingLength > 0) // If the array ID that should be remove is not the last entry.
{
Array.Copy(CurrentArray, PositionStart, newArray, RemoveArrayID, RemainingLength); // Copys the entrys behind the removed ID in the new array.
}
}
CurrentArray = newArray; // Replaces the old array with the new array.
}
else
{
Debugging.ErrorHandling.ErrorHandler("The new array size has an negative value or is not one entry smaller that the old array size.", 1202); // Creates an event log entry and error messagebox if application is run with gui.
}
}
在这个方法中的用法:
/// <summary>
/// Method that removes a certain entry from all setting arrays.
/// </summary>
/// <param name="RemoveID">ID of the setting that should be removed from the settings.</param>
private static void RemoveEntryFromSettingsArrays(int RemoveID)
{
ArrayNamesList CurrentArrays = CreateArrayDictionary(); // Creates a list of the currently used setting arrays.
GlobalVariables.FolderCount--; // Decrements the folder count by one.
foreach (string CurrentArray in CurrentArrays) // Loops through the list of arrays.
{
FieldInfo TempArrayField = typeof(GlobalVariables).GetField(CurrentArray);// Gets the current array with reflection.
Array TempArray = (Array)TempArrayField.GetValue(typeof(GlobalVariables)); // Gets value of the current array.
ArrayResize(ref TempArray, GlobalVariables.FolderCount, RemoveID); // Removes an ID from the array.
Type ArrayType = TempArray.GetType().GetElementType(); // Gets the type of the array.
TempArrayField.SetValue(ArrayType, TempArray); // Replaces the old with the new array.
}
}