在我们的项目中,我们有多个所谓的Projections
。这些Projection
- 类都有一个带有get的字符串属性,称为ProjectionTypeName
。对于所有预测,此ProjectionTypeName
应该是唯一的。
今天我遇到了两个预测具有相同ProjectionTypeName
的问题,这导致了很多麻烦。所以我决定制作一个UnitTest来防止再次发生这种情况。
我使用以下方法获取所有Types
的所有Projections
:
// The excluded abstract projections
private static readonly List<Type> AbstractProjections = new List<Type>
{
typeof(AbstractRavenDbChangesProjection),
typeof(AbstractRavenDbTimelineProjection)
};
private static IEnumerable<Type> GetAllProjectionTypes()
{
return typeof(AbstractRavenDbChangesProjection)
.Assembly
.GetTypes()
.Where(x => typeof(AbstractRavenDbChangesProjection).IsAssignableFrom(x) && !x.IsInterface)
.Except(AbstractProjections)
.ToList();
}
然后我做了实际测试:
[Test]
public void TestNoDuplicated()
{
var noDuplicatedList = new Dictionary<Type, string>();
var projectionTypes = GetAllProjectionTypes();
foreach (var type in projectionTypes)
{
// TODO: Get projectionTypeName-value by Projection's Type
var projectionTypeName = ??;
Assert.IsFalse(noDuplicatedList.ContainsValue(projectionTypeName),
"{0} has been found as ProjectionTypeName in two different Projections: {1} & {2}",
projectionTypeName,
noDuplicatedList.First(x => x.Value == projectionTypeName).Key,
type);
noDuplicatedList.Add(type, projectionTypeName);
}
}
我已经看了一下甚至试过a piece of code by @JohnSkeet,即使他说(并且我引用):
请不要这样做。永远。它很可怕。它应该被践踏, 切成小块,着火,然后再次切断。虽然好玩, 不是吗? ;)
但是看起来自2012年(发布答案时)已经改变了,当你尝试这种反思时,.NET现在会出错:"System.Security.VerificationException : Operation could destabilize the runtime."
。
所以,我的问题。当我只能处理类的ProjectionTypeName
时(而不是实际的实例化对象),如何获取字符串属性Type
的值。
如果我有一个实例化的对象,我可以做这样的事情:
myInstantiatedObject.GetType().GetProperty("ProjectionTypeName")
.GetValue(myInstantiatedObject, null);
答案 0 :(得分:2)
如何使用自定义属性呢?
[AttributeUsage(System.AttributeTargets.Class)]
public sealed class ProjectionTypeNameAttribute : Attribute
{
private string m_Name;
public string Name
{
get { return m_Name; }
}
public ProjectionTypeNameAttribute(string name)
{
m_Name = name;
}
}
[ProjectionTypeNameAttribute(ProjectionWhatever.PROJECTION_NAME)]
public class ProjectionWhatever
{
public const string PROJECTION_NAME = "Whatever";
// if you want to have property as well
public string ProjectionTypeName
{
get
{
return PROJECTION_NAME;
}
}
}
// query if type has attribute
var type = typeof(ProjectionWhatever);
var attributes = type.GetCustomAttributes(typeof(ProjectionTypeNameAttribute), false);
if (attributes != null && attributes.Length > 0)
{
var attribute = (ProjectionTypeNameAttribute)attributes[0];
// use attribute.Name
}
答案 1 :(得分:1)
好的,基于this answer,我找到了让John Skeet代码正常工作的答案。
我的问题是这一行:
var dynamicMethod = new DynamicMethod("TempUglyPropertyGetMethod", typeof(string),
Type.EmptyTypes, Assembly.GetExecutingAssembly().ManifestModule);
缺少Assembly.GetExecutingAssembly().ManifestModule
作为附加参数。这是我的工作测试代码:
// https://stackoverflow.com/questions/11162652/c-sharp-get-property-value-without-creating-instance/11162876#11162876
var method = type.GetProperty("ProjectionTypeName").GetGetMethod();
var dynamicMethod = new DynamicMethod("TempUglyPropertyGetMethod", typeof(string),
Type.EmptyTypes, Assembly.GetExecutingAssembly().ManifestModule);
var generator = dynamicMethod.GetILGenerator();
generator.Emit(OpCodes.Ldnull);
generator.Emit(OpCodes.Call, method);
generator.Emit(OpCodes.Ret);
var tempUglyPropertyGetMethod = (Func<string>)dynamicMethod.CreateDelegate(typeof(Func<string>));
var projectionTypeName = tempUglyPropertyGetMethod();
再一次,不要在实际项目中使用它。我只用它来测试这个测试用例。再次引用@JohnSkeet:
请不要这样做。 永远。它可怕。它应该被践踏 在,切成小块,着火,然后再次切断。开玩笑 虽然,不是吗? ;)