B
Brian Richards
I'm trying to write a generic function (List<TPanelType>
GetGenericPanels<TPanelType, TObjectType>()) that returns all UserControls
that derive from T and and implement an interface IGenericPropertyPanel<V>
such that U implements or derives from V. The idea being that I can discover
(via reflection) all the controls that display or allow editing of an object
properties, it's base classes and interfaces. Then I can put them in some
kind of flow layout or tabcontrol.
I have a working version (code below) however I don't think that my
methodology for ensuring that a type meets all the constraints of a generic
is good. The problem is trying to make sure that TPanelType implements
IGenericPropertyPanel<> for a class or interface that is relivent for U. Can
anyone thing of a better method of doing this? Or does anyone thing I'm just
going way overboard?
Note that I did try making base class something like class MyControl<T> :
UserControl, IGenericPropertyPanel<T> where T : SomeClass, SomeInterface and
deriving controls from there because I think the discovery process would be
simpler. Except that the designer does not support forms derived from
generic forms.
Thanks,
Brian
interface I {}
interface IGenericPropertyPanel<T> { }
class A {}
class B : A, I {}
class AControl : UserControl, IGenericPropertyPanel<A>{}
class IControl : UserControl, IGenericPropertyPanel<I>{}
GetGenericPanels<UserControl, B>(typeof(B).Assembly)
returns => List<UserControl> { new AControl(), new IControl() };
public static List<TPanelType> GetGenericPanels<TPanelType,
TObjectType>(Assembly assm)
where TPanelType : class, new()
{
List<TPanelType> panels = new List<TPanelType>();
List<Type> types = new List<Type>(assm.GetTypes());
Predicate<Type> findPanelTPanelType = delegate(Type type)
{
bool result = false;
if (typeof(TPanelType).IsAssignableFrom(type))
{
result = true;
}
return result;
};
foreach (Type type in types.FindAll(findPanelTPanelType))
{
bool addPanel = false;
List<Type> interfaces = new List<Type>(type.GetInterfaces());
if (interfaces.Contains(typeof(IGenericPropertyPanel<TObjectType>)))
{
addPanel = true;
}
else
{
foreach (Type interfaceType in interfaces)
{
if ((interfaceType.IsGenericType)
&& (typeof(IGenericPropertyPanel<>) ==
interfaceType.GetGenericTypeDefinition()))
{
foreach (Type constraint in
interfaceType.GetGenericParameterConstraints())
{
if (constraint.IsAssignableFrom(typeof(TObjectType)))
{
addPanel = true;
}
}
}
}
}
if (addPanel)
{
panels.Add(Activator.CreateInstance(type) as TPanelType);
}
}
return panels;
}
GetGenericPanels<TPanelType, TObjectType>()) that returns all UserControls
that derive from T and and implement an interface IGenericPropertyPanel<V>
such that U implements or derives from V. The idea being that I can discover
(via reflection) all the controls that display or allow editing of an object
properties, it's base classes and interfaces. Then I can put them in some
kind of flow layout or tabcontrol.
I have a working version (code below) however I don't think that my
methodology for ensuring that a type meets all the constraints of a generic
is good. The problem is trying to make sure that TPanelType implements
IGenericPropertyPanel<> for a class or interface that is relivent for U. Can
anyone thing of a better method of doing this? Or does anyone thing I'm just
going way overboard?
Note that I did try making base class something like class MyControl<T> :
UserControl, IGenericPropertyPanel<T> where T : SomeClass, SomeInterface and
deriving controls from there because I think the discovery process would be
simpler. Except that the designer does not support forms derived from
generic forms.
Thanks,
Brian
interface I {}
interface IGenericPropertyPanel<T> { }
class A {}
class B : A, I {}
class AControl : UserControl, IGenericPropertyPanel<A>{}
class IControl : UserControl, IGenericPropertyPanel<I>{}
GetGenericPanels<UserControl, B>(typeof(B).Assembly)
returns => List<UserControl> { new AControl(), new IControl() };
public static List<TPanelType> GetGenericPanels<TPanelType,
TObjectType>(Assembly assm)
where TPanelType : class, new()
{
List<TPanelType> panels = new List<TPanelType>();
List<Type> types = new List<Type>(assm.GetTypes());
Predicate<Type> findPanelTPanelType = delegate(Type type)
{
bool result = false;
if (typeof(TPanelType).IsAssignableFrom(type))
{
result = true;
}
return result;
};
foreach (Type type in types.FindAll(findPanelTPanelType))
{
bool addPanel = false;
List<Type> interfaces = new List<Type>(type.GetInterfaces());
if (interfaces.Contains(typeof(IGenericPropertyPanel<TObjectType>)))
{
addPanel = true;
}
else
{
foreach (Type interfaceType in interfaces)
{
if ((interfaceType.IsGenericType)
&& (typeof(IGenericPropertyPanel<>) ==
interfaceType.GetGenericTypeDefinition()))
{
foreach (Type constraint in
interfaceType.GetGenericParameterConstraints())
{
if (constraint.IsAssignableFrom(typeof(TObjectType)))
{
addPanel = true;
}
}
}
}
}
if (addPanel)
{
panels.Add(Activator.CreateInstance(type) as TPanelType);
}
}
return panels;
}