jeudi 10 mars 2016

Trying to get MetadataType by reflect not giving same results if I call the class directly

I'm trying to setup a T4 template that will loop through entity objects and ignore certain navigation properties based on an custom attribute I setup in the class' metdata data.

Here's the setup of the metadata tag

[MetadataType(typeof(ApplicationIntegrationMetadata))]
public partial class ApplicationIntegration
{
}

public class ApplicationIntegrationMetadata
{
    [NotToCrud]
    public ICollection<Profile> Profiles { get; set; }
}

[AttributeUsage(AttributeTargets.All)]
public class NotToCrud : System.Attribute
{
}

I've created an extension method based that checks if the class has a specific attribute on the property

    public static bool CheckIfPropertyIsAnnotated<T>(this object ctx, string propName)
    {
        var returnValue = false;

        if (!string.IsNullOrWhiteSpace(propName))
        {
            var thisType = ctx.GetType();
            var metadataTypes = thisType.GetCustomAttributes(typeof(MetadataTypeAttribute), true).OfType<MetadataTypeAttribute>().ToArray();
            var metadata = metadataTypes.FirstOrDefault();

            if (metadata != null)
            {
                var properties = metadata.MetadataClassType.GetProperties();

                var found = properties.FirstOrDefault(d => d.Name == propName);

                returnValue = found != null;

                if (returnValue)
                {
                    foreach (var propertyInfo in properties)
                    {
                        Console.WriteLine(Attribute.IsDefined(propertyInfo, typeof(T)));
                        Console.WriteLine(propertyInfo.IsDefined(typeof(T), true));
                        Console.WriteLine(propertyInfo.GetCustomAttributes(true).Length);
                        Console.WriteLine(propertyInfo.Name);
                    }
                }
            }
        }

        return returnValue;
    }

I've created two separate unit tests to find my issue.

This one works.

[TestCase("Profiles", Result = true, TestName = "Valid property")]
        public bool HasAttribute(string propName)
        {
            var test = new ApplicationIntegration();

            var actual = test.CheckIfPropertyIsAnnotated<NotToCrud>(propName);

            return actual;
        }

This one returns false

        [Test]
        public void HasAttributeWithAssembly()
        {
            var myTypes = System.Reflection.Assembly.GetAssembly(typeof(ApplicationIntegration)).GetTypes().Where(d => d.Name == "ApplicationIntegration") .ToList();

            foreach (var item in myTypes)
            {
                var actual = item.CheckIfPropertyIsAnnotated<NotToCrud>("Profiles");
                Console.WriteLine($"{item.Name} - {actual.ToString()}");
Assert.AreEqual(true, actual);
            }
        }

the problem seems to be with (var thisType = ctx.GetType())

On the second test, it returns object.GetType returned

{Name = "RuntimeType" FullName = "System.RuntimeType"}  System.RuntimeType

instead of

{Name = "ApplicationIntegration" FullName = "Apm.Model.ApplicationIntegration"}

Any clue how to get around this?





Aucun commentaire:

Enregistrer un commentaire