DotNetNewsgroup.com  
web access to complete list of Microsoft.NET newsgroups
   home   |   control panel login   |   archive  |  
 
  carried group
academic
adonet
aspnet
aspnet.announcements
aspnet.buildingcontrols
aspnet.caching
aspnet.datagridcontrol
aspnet.mobile
aspnet.security
aspnet.webcontrols
aspnet.webservices
assignment_manager
datatools
dotnet.distributed_apps
dotnet.general
dotnet.myservices
dotnet.nternationalization
dotnet.scripting
dotnet.security
dotnet.vjsharp
dotnet.vsa
dotnet.xml
dotnetfaqs
framework
framework.clr
framework.compactframework
framework.component_services
framework.controls
framework.databinding
framework.drawing
framework.enhancements
framework.interop
framework.odbcnet
framework.performance
framework.remoting
framework.sdk
framework.setup
framework.webservices
framework.windowsforms
framework.wmi
frwk.windowsforms.designtime
lang.csharp
lang.jscript
lang.vb
lang.vb.controls
lang.vb.data
lang.vb.upgrade
lang.vc
lang.vc.libraries
  
 
start date: Tue, 07 Aug 2007 10:08:10 -0700,    posted on: microsoft.public.dotnet.framework        back       

Thread Index
  1    Dan Dorey
          2    Jon Skeet [C# MVP]
                 3    Jon Skeet [C# MVP]
          4    Dan Dorey
          5    Dan Dorey


Activator Question   
My goal is to pass in an assembly and have the method return an
instance of any classes that inherit from the generic type T.

My problem is that I'm unable to cast from the result of
Activator.CreateInstance(curType) to T even though curType is a
concrete class of T (T is abstract in this case). I'm unsure why I
can't make this cast. In another method where I don't have the
restriction of T being a class, this approch works fine when T is an
interface.


I kind of feel like I'm going about this the wrong way, so if anyone
has suggestions on a better approach, please let me know :)


Thanks,
Dan


public static List<T> GetClassesByClassName<T>(Assembly assembly,
object[] classParams) where T : class
        {
            List<T> ret = new List<T>();


                foreach (Type curType in assembly.GetTypes())
                {


                    if (InheritsFrom(curType, typeof(T)) &&
curType.IsAbstract == false)
                    {
                        if (classParams == null)
                        {


ret.Add((T)Activator.CreateInstance(curType));
                        }
                        else
                        {


ret.Add((T)Activator.CreateInstance(curType, classParams));
                        }
                    }
                }


            return ret;
        }


 private static bool InheritsFrom(Type curType, Type targetType)
        {
            bool ret = false;


            while (curType.FullName != "System.Object")
            {
                if (curType.FullName == targetType.FullName)
                {
                    ret = true;
                    break;
                }
                else
                {
                    curType = curType.BaseType;
                }
            }


            return ret;
        }
Date:Tue, 07 Aug 2007 10:08:10 -0700   Author:  

Re: Activator Question   
Dan Dorey  wrote:

> My goal is to pass in an assembly and have the method return an
> instance of any classes that inherit from the generic type T.
> 
> My problem is that I'm unable to cast from the result of
> Activator.CreateInstance(curType) to T even though curType is a
> concrete class of T (T is abstract in this case). I'm unsure why I
> can't make this cast. In another method where I don't have the
> restriction of T being a class, this approch works fine when T is an
> interface.
> 
> I kind of feel like I'm going about this the wrong way, so if anyone
> has suggestions on a better approach, please let me know :)


Well, instead of InheritsFrom, you'd be better off using 
Type.IsAssignableFrom or Type.IsSubclassOf.

However, I don't get any compile-time errors with your code.

Could you post a short but complete program which demonstrates the
problem?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that.

-- 
Jon Skeet - 
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Date:Tue, 7 Aug 2007 18:14:08 +0100   Author:  

Re: Activator Question   
well interestingly enough, I made a quick test app so I could show you
the problem, but it appears my test app works just fine. Also note
that the casting error I was getting before was at runtime not when
compiling.

I had to use my ugly method of testing for inhertience because
IsSubclass and IsAssignableFrom were returning false for me.
Interestingly IsAssignableFrom returns true if my class Action is NOT
abstract. Clearly I'm missing something about the workings of these
methods.

I'll have to start changing my test app so that it's closer and closer
to the real thing and see when it breaks. Here is the test app and if
you have any thoughts let me know. Thanks for getting me to do the
test app... at least I know it's possible now with this approch.

Thanks,
Dan


*******************************************************************


>From a startup project, you have to add this line of code:


DynamicLoader.GetClassesByClassName<Node>(Directory.GetCurrentDirectory()
+ @"\PluginTester.dll", null);

********************************************************************

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Reflection;

namespace PluginTester
{
    public abstract class Node
    {
        public abstract string NodeID { get; }
    }

    public abstract class Action : Node
    {
        //public abstract string NodeID { get; }
        public abstract string ActionID { get; }

    }

    public class MyAction : Action
    {
        public override string NodeID
        {
            get
            {
                return "MyAction";
            }
        }
        public override string ActionID
        {
            get { return "MyActionID"; }
        }
    }

    public class DynamicLoader
    {
        public static List<T> GetClassesByClassName<T>(string
fileName, object[] classParams) where T : class
        {
            List<T> ret = new List<T>();

            Assembly assembly = Assembly.LoadFrom(fileName);
            foreach (Type curType in assembly.GetTypes())
            {

                if (InheritsFrom(curType, typeof(T)) &&
curType.IsAbstract == false)
                {
                    if (classParams == null)
                    {
                        ret.Add((T)Activator.CreateInstance(curType));
                    }
                    else
                    {
                        ret.Add((T)Activator.CreateInstance(curType,
classParams));
                    }
                }
            }

            return ret;
        }

        private static bool InheritsFrom(Type curType, Type
targetType)
        {
            bool ret = false;

            while (curType.FullName != "System.Object")
            {
                if (curType.FullName == targetType.FullName)
                {
                    ret = true;
                    break;
                }
                else
                {
                    curType = curType.BaseType;
                }
            }

            return ret;
        }

    }




}
Date:Tue, 07 Aug 2007 11:14:24 -0700   Author:  

Re: Activator Question   
Well I just copied all the code from my mainline application into the
test app and it works there :S I should be able to figure it out from
here even if it doesn't make sense at the moment.
Date:Tue, 07 Aug 2007 11:23:33 -0700   Author:  

Re: Activator Question   
Dan Dorey  wrote:

> well interestingly enough, I made a quick test app so I could show you
> the problem, but it appears my test app works just fine. Also note
> that the casting error I was getting before was at runtime not when
> compiling.


Right. Should the type involved definitely have "worked"?
 

> I had to use my ugly method of testing for inhertience because
> IsSubclass and IsAssignableFrom were returning false for me.
> Interestingly IsAssignableFrom returns true if my class Action is NOT
> abstract. Clearly I'm missing something about the workings of these
> methods.


Could you give a concrete example of this? It always returns the same 
result for me, using:

            Console.WriteLine ("ret={0}", ret);
            Console.WriteLine ("IsAssignableFrom={0}", 
                               targetType.IsAssignableFrom(curType));

at the bottom of InheritsFrom.


> I'll have to start changing my test app so that it's closer and closer
> to the real thing and see when it breaks. Here is the test app and if
> you have any thoughts let me know. Thanks for getting me to do the
> test app... at least I know it's possible now with this approch.


My only other request is that you include a suitable Main method so we 
know what we're dealing with :) Also, if you use the currently 
executing assembly rather than using a filename, it'll make testing 
easier.

-- 
Jon Skeet - 
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Date:Tue, 7 Aug 2007 19:26:40 +0100   Author:  

Google
 
Web dotnetnewsgroup.com


COPYRIGHT ?2005, EUROFRONT WORLDWIDE LTD., ALL RIGHT RESERVE  |   Contact us