反思:从提供的 属性 值中获取 Class 名称
Reflection: Get Class name from supplied property value
我有一个基数 class,其中有多个 child classes。
每个 class 都有一个 GetType 属性,它将 return 指定的枚举值。
当我提供枚举值时是否可以获得 class 名称?
示例:
public enum EnumClassNames
{
Class1 = 1,
Class2 = 2,
}
class MySubClass : ParentClass
{
public override EnumType MyType()
{
return EnumType.Class1;
}
}
void main()
{
var className = xxxx(EnumType.Class1); //I would like to get the value MySubClass back here.
}
编辑:
一点背景。我有一个 Message parent class 将处理队列中的消息。每个 'kind-of' 消息 subclass 将覆盖一个 ProcessMessage 函数。
我还有 Queue class,它将遍历 Queue 并处理每条消息。所以 "correct" 选项可能会显式实例化队列 class 中每个 child class 的 object 并调用 ChildClass.ProcessMessage,但是通过添加新的 MessageType 最大限度地减少维护,我想 "read" child class 的名称并从那里实例化一个 object。这将在添加新消息类型时防止额外的 if- 和 switch 语句。
您将必须扫描 Assembly
以查找从 ParentClass
继承的所有类型,然后创建每个派生的实例 class,调用方法来获取EnumType
值并找到对应于搜索值的 subclass。假设所有派生类型都在同一个程序集中 - 否则您将不得不扫描所有 assemblies/known 个程序集。
详细说明您要实现的目标,肯定有比这更好的方法。
我不会为此创建方法,因为您需要一个实例来调用该方法。但是,您可以创建一个静态 属性 类型 returns。也许属性会更好。
我创建了一个fiddle作为示例:https://dotnetfiddle.net/IweLy7
它依赖于扫描程序集以查找相关类型。如其他答案所述,您可能需要检查用例的其他程序集。
你可以通过GetType().ToString()
方法获取对象的类型,然后将其转换为枚举。
public override EnumClassNames MyType()
{
string stringifiedType = this.GetType().ToString();
var myEnumType = (EnumClassNames)Enum.Parse(typeof(EnumClassNames), stringifiedType);
return myEnumType;
}
如果您不确定要转换的类型,也可以使用 Enum.TryParse()
方法。
根据你编辑的问题,我给你一个基本的想法。
假设有消息类型:
// Message types
class Message { }
class MessageA : Message { }
class MessageB : Message { }
和基本消息处理器:
interface IMessageProcessor
{
void ProcessMessage(Message message);
}
abstract class MessageProcessor<TMessage> : IMessageProcessor
where TMessage : Message
{
protected abstract void ProcessMessage(TMessage message);
public void ProcessMessage(Message message)
{
ProcessMessage((TMessage)message);
}
}
您需要将特定消息类型绑定到其自定义处理器。这可以使用一些元数据来完成,也就是说,您需要自定义属性:
// Mapping attribute
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
class MessageProcessorAttribute : Attribute
{
public MessageProcessorAttribute(Type messageType)
{
MessageType = messageType;
}
public Type MessageType { get; }
}
现在您可以声明消息处理器:
[MessageProcessor(typeof(MessageA))]
class MessageAProcessor : MessageProcessor<MessageA>
{
protected override void ProcessMessage(MessageA message)
{
Console.WriteLine("Processing A message...");
}
}
[MessageProcessor(typeof(MessageB))]
class MessageBProcessor : MessageProcessor<MessageB>
{
protected override void ProcessMessage(MessageB message)
{
Console.WriteLine("Processing B message...");
}
}
这是示例队列,它将使用上面的代码:
// Message queue
class MessageQueue
{
private readonly Queue<Message> messages;
public MessageQueue()
{
messages = new Queue<Message>();
}
public void PostMessage(Message message)
{
messages.Enqueue(message);
}
public void ProcessMessages()
{
while (messages.Any())
{
var message = messages.Dequeue();
var messageProcessor = GetMessageProcessorOrDefault(message);
messageProcessor?.ProcessMessage(message);
}
}
private IMessageProcessor GetMessageProcessorOrDefault(Message message)
{
var messageType = message.GetType();
var messageProcessorTypes = GetMessageProcessorTypes();
var messageProcessorType = messageProcessorTypes
.FirstOrDefault(mpt => mpt.GetCustomAttribute<MessageProcessorAttribute>()?.MessageType == messageType);
return messageProcessorType != null ? (IMessageProcessor)Activator.CreateInstance(messageProcessorType) : null;
}
private IEnumerable<Type> GetMessageProcessorTypes()
{
// TODO: scan assemblies to retrieve IMessageProcessor implementations
return new[]
{
typeof(MessageAProcessor),
typeof(MessageBProcessor)
};
}
}
您可以将此方法与 DI 容器相结合,并构建基于插件的应用程序 - 消息类型和处理器的数量,因为它们的位置(同一个程序集或多个程序集)并不重要。
更新。我添加了一些泛型以避免在每个后代中进行类型转换。
我有一个基数 class,其中有多个 child classes。 每个 class 都有一个 GetType 属性,它将 return 指定的枚举值。 当我提供枚举值时是否可以获得 class 名称?
示例:
public enum EnumClassNames
{
Class1 = 1,
Class2 = 2,
}
class MySubClass : ParentClass
{
public override EnumType MyType()
{
return EnumType.Class1;
}
}
void main()
{
var className = xxxx(EnumType.Class1); //I would like to get the value MySubClass back here.
}
编辑: 一点背景。我有一个 Message parent class 将处理队列中的消息。每个 'kind-of' 消息 subclass 将覆盖一个 ProcessMessage 函数。
我还有 Queue class,它将遍历 Queue 并处理每条消息。所以 "correct" 选项可能会显式实例化队列 class 中每个 child class 的 object 并调用 ChildClass.ProcessMessage,但是通过添加新的 MessageType 最大限度地减少维护,我想 "read" child class 的名称并从那里实例化一个 object。这将在添加新消息类型时防止额外的 if- 和 switch 语句。
您将必须扫描 Assembly
以查找从 ParentClass
继承的所有类型,然后创建每个派生的实例 class,调用方法来获取EnumType
值并找到对应于搜索值的 subclass。假设所有派生类型都在同一个程序集中 - 否则您将不得不扫描所有 assemblies/known 个程序集。
详细说明您要实现的目标,肯定有比这更好的方法。
我不会为此创建方法,因为您需要一个实例来调用该方法。但是,您可以创建一个静态 属性 类型 returns。也许属性会更好。
我创建了一个fiddle作为示例:https://dotnetfiddle.net/IweLy7
它依赖于扫描程序集以查找相关类型。如其他答案所述,您可能需要检查用例的其他程序集。
你可以通过GetType().ToString()
方法获取对象的类型,然后将其转换为枚举。
public override EnumClassNames MyType()
{
string stringifiedType = this.GetType().ToString();
var myEnumType = (EnumClassNames)Enum.Parse(typeof(EnumClassNames), stringifiedType);
return myEnumType;
}
如果您不确定要转换的类型,也可以使用 Enum.TryParse()
方法。
根据你编辑的问题,我给你一个基本的想法。
假设有消息类型:
// Message types
class Message { }
class MessageA : Message { }
class MessageB : Message { }
和基本消息处理器:
interface IMessageProcessor
{
void ProcessMessage(Message message);
}
abstract class MessageProcessor<TMessage> : IMessageProcessor
where TMessage : Message
{
protected abstract void ProcessMessage(TMessage message);
public void ProcessMessage(Message message)
{
ProcessMessage((TMessage)message);
}
}
您需要将特定消息类型绑定到其自定义处理器。这可以使用一些元数据来完成,也就是说,您需要自定义属性:
// Mapping attribute
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
class MessageProcessorAttribute : Attribute
{
public MessageProcessorAttribute(Type messageType)
{
MessageType = messageType;
}
public Type MessageType { get; }
}
现在您可以声明消息处理器:
[MessageProcessor(typeof(MessageA))]
class MessageAProcessor : MessageProcessor<MessageA>
{
protected override void ProcessMessage(MessageA message)
{
Console.WriteLine("Processing A message...");
}
}
[MessageProcessor(typeof(MessageB))]
class MessageBProcessor : MessageProcessor<MessageB>
{
protected override void ProcessMessage(MessageB message)
{
Console.WriteLine("Processing B message...");
}
}
这是示例队列,它将使用上面的代码:
// Message queue
class MessageQueue
{
private readonly Queue<Message> messages;
public MessageQueue()
{
messages = new Queue<Message>();
}
public void PostMessage(Message message)
{
messages.Enqueue(message);
}
public void ProcessMessages()
{
while (messages.Any())
{
var message = messages.Dequeue();
var messageProcessor = GetMessageProcessorOrDefault(message);
messageProcessor?.ProcessMessage(message);
}
}
private IMessageProcessor GetMessageProcessorOrDefault(Message message)
{
var messageType = message.GetType();
var messageProcessorTypes = GetMessageProcessorTypes();
var messageProcessorType = messageProcessorTypes
.FirstOrDefault(mpt => mpt.GetCustomAttribute<MessageProcessorAttribute>()?.MessageType == messageType);
return messageProcessorType != null ? (IMessageProcessor)Activator.CreateInstance(messageProcessorType) : null;
}
private IEnumerable<Type> GetMessageProcessorTypes()
{
// TODO: scan assemblies to retrieve IMessageProcessor implementations
return new[]
{
typeof(MessageAProcessor),
typeof(MessageBProcessor)
};
}
}
您可以将此方法与 DI 容器相结合,并构建基于插件的应用程序 - 消息类型和处理器的数量,因为它们的位置(同一个程序集或多个程序集)并不重要。
更新。我添加了一些泛型以避免在每个后代中进行类型转换。