mardi 16 juillet 2019

Create a Lambda Expression Based Around Type Variables

Background

As a little test project related to reflection and search I have classes and their child properties with attributes indicating the relevant classes and properties are searchable.

It looks like this for a class.

[SearchableClass(SearchId = "myModelSearchId")]
public class MyModel

And this for the some properties with a class.

[SearchField(SearchId = "myPropertySearchId")]
public string MyProperty { get; set; }

With properties like this.

[AttributeUsage(AttributeTargets.Class)]
public class SearchableClass : Attribute
{
    public string SearchId { get; set; }
}

[AttributeUsage(AttributeTargets.Property)]
public class SearchField : Attribute
{
    public string SearchId { get; set; }
}

Aim

On application start would like to find matching classes/properties and store them in a way to allow me access them later in a generic way given information I've retrieved via the attributes.

Current Work

//Little class to represent fields

public class FieldMappingEntry
{
    public Func<object, object> Func { get; set; } //return field value given parent class
    public Type FieldType { get; set; } //can be used for casting to correct type
}

//...

//Setup dictionary to track search class/field information

var fieldMapping = new Dictionary<string, Dictionary<string, FieldMappingEntry>>();

//...

//Code to find classes and add them

foreach (var matchingClass in Assembly.GetExecutingAssembly().GetTypes().Where(t => t.GetCustomAttributes(typeof(SearchableClass), true).Length > 0))
{
    var searchableClassAttribute = (SearchableClass)matchingClass.GetCustomAttributes(typeof(SearchableClass), true)[0];
    var newFieldDictionary = new Dictionary<string, FieldMappingEntry>();
    fieldMapping.Add(searchableClassAttribute.SearchId, newFieldDictionary);
    foreach (var matchingField in matchingClass.GetProperties().Where(p => Attribute.IsDefined(p, typeof(SearchField), true)))
    {
        var searchFieldAttribute = (SearchField)matchingField.GetCustomAttributes(typeof(SearchField), true)[0];
        //on line below would like to assign Func field
        newFieldDictionary.Add(searchFieldAttribute.SearchId, new FieldMappingEntry { FieldType = matchingField.ReflectedType });
    }
}

On the last line with code, I'd like to create a function and assign it to Func that for our example would look like this.

model => model.MyProperty

Any ideas how I would achieve that?





Aucun commentaire:

Enregistrer un commentaire