mardi 12 mai 2015

How do I specify that I want to match any type parameter of a generic C# class?

I have a C# generic where I would like to have a function that looks through the properties of any class that is derived from this generic via reflection for other properties that also are this generic (though not necessarily the same type as the caller). I'm running into two problems with the approach I am using. The first is that VS insists that my class can never be the type that I am looking for. The second is that when I run into an IEnumerable, I want to look for IEnumerables that contain any type that derives from the generic base class without providing a parameter. An example follows:

public abstract class BaseClass<T> where T : BaseClass<T>
{
    public T Identity
    {
        get { return GetIdentity(); }
    }

    protected abstract T GetIdentity();

    public IEnumerable<TOtherType> GetMembers<TOtherType>() where TOtherType : BaseClass<TOtherType>
    {
        // First problem, Visual Studio: "The given expression is never of the provided type." Why?
        if (this is TOtherType)
        {
            yield return this as TOtherType;
        }

        var props = GetType().GetProperties();
        foreach (var propertyInfo in props)
        {
            var propertyValue = propertyInfo.GetMethod.Invoke(this, null);
            if (propertyValue is TOtherType)
            {
                var ot = propertyValue as TOtherType;
                foreach (var retVal in ot.GetMembers<TOtherType>())
                {
                    yield return retVal;
                }
            }

            // This is the other problem: How do I specify that it can be any "BaseClass"?
            else if (propertyValue is IEnumerable<BaseClass>) 
            {
                var listVal = propertyValue as IEnumerable<BaseClass>;
                foreach (var subEntry in listVal)
                {
                    foreach (var retVal in subEntry.GetMembers<TOtherType>())
                    {
                        yield return retVal;
                    }
                }
            }
        }
    }
}

public class OtherClass : BaseClass<OtherClass>
{
    protected override OtherClass GetIdentity()
    {
        return new OtherClass();
    }
}

public class DerivedClass : BaseClass<DerivedClass>
{
    public DerivedClass()
    {
        OtherClasses = new List<OtherClass>();
    }

    public List<OtherClass> OtherClasses { get; private set; }

    protected override DerivedClass GetIdentity()
    {
        var id = new DerivedClass();
        return id;
    }
}





Aucun commentaire:

Enregistrer un commentaire