By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,414 Members | 1,057 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,414 IT Pros & Developers. It's quick & easy.

Generic constraints

P: n/a
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;
}
Jun 8 '06 #1
Share this Question
Share on Google+
2 Replies


P: n/a
Brian,

Why not go the other way with it? Since you are using reflection, why
not have an attribute that the types attach to themselves (or have an
attribute on the assembly level that exposes the types that the assembly
wants to expose) and then get the type from that. Then, all you have to do
is create it.

The assumption would be that the type is responsible for saying "hey, I
conform to what you are looking for" and you take it's word for it.

Additionally, you now have an easy switch to turn off a panel if you
don't want it, or give the choice to those that expose these types that
happen to conform to your pattern. It also helps to solidfy the
relationship and the intent of your panel types.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Brian Richards" <br*******@gmail.com> wrote in message
news:uu**************@TK2MSFTNGP02.phx.gbl...
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;
}

Jun 8 '06 #2

P: n/a
The problem with the attribute approach is that I don't get compile time
checking on the panel type signatures (IGenericPropertyPanel<T>). And I need
those signatures in order to set the display object of the control.
Additionally I was looking to extend the method to be able to get only the
most specific control for a given type. So that if I have
class A
class B : A
class C : A
class D : B
class ControlA : IGenericPropertyPanel<A>
class ControlB : IGenericPropertyPanel<B>

GetPropertyPanel<Panel, A> => ControlA
GetPropertyPanel<Panel, B> => ControlB
GetPropertyPanel<Panel, C> => ControlA
GetPropertyPanel<Panel, D> => ControlB

Thanks for your input.

-Brian

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com> wrote in
message news:%2****************@TK2MSFTNGP05.phx.gbl...
Brian,

Why not go the other way with it? Since you are using reflection, why
not have an attribute that the types attach to themselves (or have an
attribute on the assembly level that exposes the types that the assembly
wants to expose) and then get the type from that. Then, all you have to do is create it.

The assumption would be that the type is responsible for saying "hey, I conform to what you are looking for" and you take it's word for it.

Additionally, you now have an easy switch to turn off a panel if you
don't want it, or give the choice to those that expose these types that
happen to conform to your pattern. It also helps to solidfy the
relationship and the intent of your panel types.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Brian Richards" <br*******@gmail.com> wrote in message
news:uu**************@TK2MSFTNGP02.phx.gbl...
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;
}


Jun 8 '06 #3

This discussion thread is closed

Replies have been disabled for this discussion.