我有windows app在哪里我需要在运行时通过读取名为“Controls.txt”的文本文件来填充枚举值。 作为限制,我不打算使用字典。以下是枚举MyControls中可用的默认值。 我只能使用枚举。
public enum MyControls
{
Button1 = 0,
Button2 = 1,
Button3 = 2,
}
如果Controls.txt文件可用,则枚举内容应更改为
public enum MyControls
{
btn1 = 0,
btn2 = 1,
btn3 = 2,
}
我如何实现这一目标。我也看到了链接Creating / Modifying Enums at Runtime,但无法理解。
答案 0 :(得分:4)
我强烈认为你正试图解决错误的问题。枚举的值是类型安全的。我认为动态填充它并不是一个好主意。真正有用的是在编译之前使用文本文件(例如)填充枚举,甚至。您可以使用VS中的文本模板执行此操作。
您可以在我的博客文章中找到一个示例:http://skleanthous.azurewebsites.net/post/2014/05/21/Creating-enums-from-the-database-and-using-them-in-Entity-framework-5-and-later-in-model-first
虽然我的示例从数据库加载,但将其更改为从文本文件加载应该是微不足道的。
答案 1 :(得分:3)
除了我同意另一个回答说你丢失类型和编译时安全的事实,使用EnumBuilderClass
应该是唯一的方法(感谢huMpty duMpty的评论)。
// sample "file":
string fileContent = @"
btn1 = 0,
btn2 = 1,
btn3 = 2,
";
var enumBody = fileContent.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)
.Select(line => new { bothToken = line.Trim().Trim(',').Split('=') })
.Where(x => x.bothToken.Length == 2)
.Select(x => new { Name = x.bothToken[0].Trim(), Value = int.Parse(x.bothToken[1].Trim()) });
AppDomain currentDomain = AppDomain.CurrentDomain;
AssemblyName asmName = new AssemblyName("EnumAssembly");
AssemblyBuilder asmBuilder = currentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);
ModuleBuilder mb = asmBuilder.DefineDynamicModule(asmName.Name, asmName.Name + ".dll");
string enumTypeName = string.Format("{0}.{1}", typeof(MyControls).Namespace, typeof(MyControls).Name);
EnumBuilder eb = mb.DefineEnum(enumTypeName, TypeAttributes.Public, typeof(int));
foreach(var element in enumBody)
{
FieldBuilder fb1 = eb.DefineLiteral(element.Name, element.Value);
}
Type eType = eb.CreateType();
foreach (object obj in Enum.GetValues(eType))
{
Console.WriteLine("{0}.{1} = {2}", eType, obj, ((int)obj));
}
输出:
Namespacename.MyControls.btn1 = 0
Namespacename.MyControls.btn2 = 1
Namespacename.MyControls.btn3 = 2
答案 2 :(得分:0)
嗯,我同意上面的用例不是我会使用的。但是,我不同意它没有用处。我们使用例如使用枚举来为机器学习模块分类字符串值。我们在运行时编写代码以在运行时使用它,分组枚举比分组和分析字符串要快得多。使用大品质的弦乐时没有什么好处。在进行比较,内存分配,垃圾收集,分组,排序时,它们是有问题的,只有太多的字节。
管理大量数据的数据库将生成字符串的散列并存储该字符串,然后比较字符串散列(不唯一但是数字)和同一语句中的字符串,使得TSQL语言使用更有效的索引哈希字段缩小搜索范围,然后比较字符串值以确保使用正确的值。在TSQL中,人们可以这样做
SELECT *
FROM Production.Product
WHERE CHECKSUM(N'Bearing Ball') = cs_Pname
AND Name = N'Bearing Ball';
GO
但在.net中我们一直认为比较字符串是可行的方法。
我把我的代码转储到这里是没有意义的,因为它是专有的但是那里有很多好的样本,Bob Dain的文章逐行显示了如何做到这一点并且位于{{3} }
他的解决方案的片段如下:
using System;
using System.Reflection;
using System.IO;
namespace RemoteUser
{
public class RemoteUserClass
{
public RemoteUserClass()
{
// Load the remote assembly
AssemblyName name = new AssemblyName();
name.CodeBase = "file://" + Directory.GetCurrentDirectory() +
"ThirdPartyDll.dll";
Assembly assembly = AppDomain.CurrentDomain.Load(name);
// Instantiate the class
object remoteObject =
assembly.CreateInstance("ThirdPartyDll.ThirdPartyClass");
Type remoteType =
assembly.GetType("ThirdPartyDll.ThirdPartyClass");
// Load the enum type
PropertyInfo flagsInfo =
remoteType.GetProperty("ThirdPartyBitFields");
Type enumType = assembly.GetType("ThirdPartyDll.BitFields");
// Load the enum values
FieldInfo enumItem1 = enumType.GetField("AnotherSetting");
FieldInfo enumItem2 = enumType.GetField("SomethingElse");
// Calculate the new value
int enumValue1 = (int)enumItem1.GetValue(enumType);
int enumValue2 = (int)enumItem2.GetValue(enumType);
int currentValue = (int)flagsInfo.GetValue(remoteObject, null);
int newValue = currentValue | enumValue1 | enumValue2;
// Store the new value back in Options.FieldFlags
object newEnumValue = Enum.ToObject(enumType, newValue);
flagsInfo.SetValue(remoteObject, newEnumValue, null);
// Call the method
MethodInfo method = remoteType.GetMethod("DoSomeGood");
method.Invoke(remoteObject, null);
}
}
}
可以将System.Reflection.Emit命名空间用于许多事情,可以生成一个为其创建许可证密钥的类。人们也可以编写代码,代码编写和更新代码是未来。
希望增加一些新观点
快乐编码
沃尔特