mercredi 2 septembre 2015

Reflection: Property-GetValue by Class-Type (so without an instantiated Object)

In our project we have multiple so-called Projections. These Projection-classes all have a string property with a get, called ProjectionTypeName. This ProjectionTypeName should be unique for all Projections.

Today I had the problem where two Projections had the same ProjectionTypeName which caused quite a lot of trouble. So I decided to make a UnitTest to prevent this from happening again.

I use the following method to get all the Types of all the 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();
}

Then I made the actual test:

[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);
    }   
}

I've looked around a bit and even tried a piece of code by @JohnSkeet, even though he states (and I quote): "Please don't do this. Ever. It's ghastly. It should be trampled on, cut up into little bits, set on fire, then cut up again. Fun though, isn't it? ;)"

But it looks like this has been changed since 2012 (when the answer was posted) and .NET now gives an error when you try this kind of reflection: "System.Security.VerificationException : Operation could destabilize the runtime.".

So, my question. How do I get the value of the string-property ProjectionTypeName, when I only have the Type of the class to my disposal (and not an actual instantiated object).

If I would had an instantiated object I would be able to do something like this:

myInstantiatedObject.GetType().GetProperty("ProjectionTypeName")
    .GetValue(myInstantiatedObject, null);





Aucun commentaire:

Enregistrer un commentaire