473,385 Members | 2,004 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Problems with IsSubclassOf

Hi all,

I'm building a user control in c#. This control has a property which
can contain an instance of a user defined class which has to be a
subclass of an abstract class A. I'd like the user of the control to be
able at design time to select the value of this property from a
dropdownlist showing all the subclasses of A that can be found in the
assemblies referenced in the project, so I wrote my own UITypeEditor
and at first everything seemed to be fine.
But then I noticed that the list in my editor displays only the
subclasses of A that are contained in assemblies which were referenced
before the control was added to the form, while it ignores the ones
contained in assemblies added after the creation of the control.
I found out that the even the classes contained in these late
assemblies are correctly identified by my code, but that the result of
the IsSubclassOf method is false instead of true.
This is a sample of what I'm doing (rs is an ITypeResolutionService):

Solution sol = currentDTE.Solution;
aList=new ArrayList();
foreach (Project prj in sol.Projects)
{
VSProject vsPrj=(VSProject) prj.Object;
References refs = vsPrj.References;
foreach (Reference aRef in refs)
{
AssemblyName aName=new AssemblyName();
aName.Name=aRef.Name;
Assembly anAssembly=rs.GetAssembly(aName);
if (anAssembly!=null)
{
Type[] types=anAssembly.GetTypes();
foreach (Type t in types)
{
if (t.IsClass && !t.IsAbstract && t.IsSubclassOf(typeof(A)))
aList.Add(t.FullName);
}
}
}
}

Can you tell me what I'm doing wrong?

Many thanks,

Francesco.

Jan 17 '06 #1
9 3919
Paguro Bernardo wrote:
I'm building a user control in c#. This control has a property which
can contain an instance of a user defined class which has to be a
subclass of an abstract class A. I'd like the user of the control to be
able at design time to select the value of this property from a
dropdownlist showing all the subclasses of A that can be found in the
assemblies referenced in the project, so I wrote my own UITypeEditor
and at first everything seemed to be fine.


Do you have class A defined in multiple assemblies by any chance?
That's usually the problem.

Jon

Jan 17 '06 #2

Jon Skeet [C# MVP] ha scritto:
Paguro Bernardo wrote:
I'm building a user control in c#. This control has a property which
can contain an instance of a user defined class which has to be a
subclass of an abstract class A. I'd like the user of the control to be
able at design time to select the value of this property from a
dropdownlist showing all the subclasses of A that can be found in the
assemblies referenced in the project, so I wrote my own UITypeEditor
and at first everything seemed to be fine.


Do you have class A defined in multiple assemblies by any chance?
That's usually the problem.

Jon


Wow, faster than light!

It seems to me that class A is defined in just a single assembly, which
is referenced by three different assemblies: the one defining its
subclasses, the one defining the UITypeEditor, and the one defining the
user control. All these assemblies are located in the same directory,
and all of them are referenced in the project where I'm testing this
stuff. Can this be a problem?

Thanks again,
Francesco.

Jan 17 '06 #3
Paguro Bernardo wrote:
Do you have class A defined in multiple assemblies by any chance?
That's usually the problem.


It seems to me that class A is defined in just a single assembly, which
is referenced by three different assemblies: the one defining its
subclasses, the one defining the UITypeEditor, and the one defining the
user control. All these assemblies are located in the same directory,
and all of them are referenced in the project where I'm testing this
stuff. Can this be a problem?


So all the assemblies are in the same directory at runtime? That should
be okay.

Could you post a short but complete example which demonstrates the
problem?
See http://www.pobox.com/~skeet/csharp/complete.html for what I mean by
that.

You might want to go into the debugger having got both typeof(A) and
myType.BaseType into separate variables, and compare the two of them
for equality.

Jon

Jan 17 '06 #4
Jon Skeet [C# MVP] ha scritto:

So all the assemblies are in the same directory at runtime? That should
be okay.
Well, not exactly at runtime. I'm trying to add a control to a form at
design time, and the inheritance test is done when editing one of the
control properties.
Could you post a short but complete example which demonstrates the
problem?
See http://www.pobox.com/~skeet/csharp/complete.html for what I mean by
that.
For the time being I can't reach that URL because a stupid proxy
categorizes it as Health, and I'm not allowed to reach it from the
office. I'll take a look at it later and will will post the example.
You might want to go into the debugger having got both typeof(A) and
myType.BaseType into separate variables, and compare the two of them
for equality.

That's not so easy for me, since I'm quite a beginner and I'm not able
to debug this kind of things yet (debugging something at design time is
still black magic to me).

Francesco.

Jan 17 '06 #5
[Looks like my previous reply didn't make it - apologies if this shows
up twice]

Paguro Bernardo wrote:
So all the assemblies are in the same directory at runtime? That should
be okay.
Well, not exactly at runtime. I'm trying to add a control to a form at
design time, and the inheritance test is done when editing one of the
control properties.


Ouch. Okay - I don't know much about design-time stuff, I'm afraid.
Could you post a short but complete example which demonstrates the
problem?
See http://www.pobox.com/~skeet/csharp/complete.html for what I mean by
that.


For the time being I can't reach that URL because a stupid proxy
categorizes it as Health, and I'm not allowed to reach it from the
office. I'll take a look at it later and will will post the example.


Try going to http://www.yoda.arachsys.com/csharp/complete.html instead
- it's the same page, pobox.com is just a redirection service.
You might want to go into the debugger having got both typeof(A) and
myType.BaseType into separate variables, and compare the two of them
for equality.

That's not so easy for me, since I'm quite a beginner and I'm not able
to debug this kind of things yet (debugging something at design time is
still black magic to me).


In that case, I suggest you work out what the interesting information
might be, and make your class write it out to a log (preferrably a
plain text file somewhere, so it's easy to work out whether or not it's
working). It's a bit slow and painful, but may well be easier than
trying to do design-time debugging.

Jon

Jan 17 '06 #6
Paguro Bernardo wrote:
So all the assemblies are in the same directory at runtime? That should
be okay.

Well, not exactly at runtime. I'm trying to add a control to a form at
design time, and the inheritance test is done when editing one of the
control properties.


Ah. Okay, that's likely to be entirely different then. Hmm.
Could you post a short but complete example which demonstrates the
problem?
See http://www.pobox.com/~skeet/csharp/complete.html for what I mean by
that.


For the time being I can't reach that URL because a stupid proxy
categorizes it as Health, and I'm not allowed to reach it from the
office. I'll take a look at it later and will will post the example.


Try http://www.yoda.arachsys.com/csharp/complete.html - pobox.com is
just a redirector.
You might want to go into the debugger having got both typeof(A) and
myType.BaseType into separate variables, and compare the two of them
for equality.


That's not so easy for me, since I'm quite a beginner and I'm not able
to debug this kind of things yet (debugging something at design time is
still black magic to me).


That's understandable. I haven't done any design-time stuff at all, so
I'd probably be doing even worse.

You could cheat a little though - open a file and write log entries
with all the information you'd get from the debugger. It's a bit
painful, but should work.

Jon

Jan 17 '06 #7

Jon Skeet [C# MVP] ha scritto:
Try http://www.yoda.arachsys.com/csharp/complete.html - pobox.com is
just a redirector.

The redirector is OK, its yoda the "health" site. Anyway, in the
evening the damn thing is down, so I was able to reach your page. It's
always nice to meet another Catan's settler.

This is exactly what I'm trying to do:

I've got the following assemblies:
------------------------------------------------------------------------------------
the assembly MyBaseClass defining just the following class:

using System;

namespace MyBaseClass
{
public class BaseClass
{
public BaseClass()
{
}
}
}
------------------------------------------------------------------------------------
the assembly MyDerivedClasses which references MyBaseClass and contains
2 derived classes: DerivedA and DerivedB:
using System;
using MyBaseClass;

namespace MyDerivedClasses
{
public class DerivedA : BaseClass
{
public DerivedA()
{
}
}

public class DerivedB : BaseClass
{
public DerivedB()
{
}
}
}
--------------------------------------------------------------------------------------------------
the assembly MyTypeEditor, which references MyBaseClass and the System
assemblies System, System.Drawing.Design, System.Windows.Forms.Design,
System.Windows.Forms, System.ComponentModel.Design, System.Reflection,
EnvDTE, VSLangProj.
This assembly defines MyEditor as follows:

using System;
using System.Drawing.Design;
using System.Windows.Forms.Design;
using System.Windows.Forms;
using System.ComponentModel.Design;
using System.Reflection;
using EnvDTE;
using VSLangProj;
using MyBaseClass;
namespace MyTypeEditor
{
public class MyEditor : UITypeEditor
{
IWindowsFormsEditorService edSvc;
ListBox lista;

public MyEditor()
{
}

public override UITypeEditorEditStyle GetEditStyle(
System.ComponentModel.ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.DropDown;
}

public override object
EditValue(System.ComponentModel.ITypeDescriptorCon text context,
System.IServiceProvider provider, object value)
{
ITypeResolutionService rs;
DTE currentDTE;

edSvc
=(IWindowsFormsEditorService)provider.GetService(t ypeof(IWindowsFormsEditorService));
rs =
(ITypeResolutionService)context.GetService(typeof( ITypeResolutionService));
currentDTE = (DTE)context.GetService(typeof(DTE));

Solution sol = currentDTE.Solution;
lista=new ListBox();
foreach (Project prj in sol.Projects)
{
VSProject vsPrj=(VSProject) prj.Object;
References refs = vsPrj.References;
foreach (Reference aRef in refs)
{
if (!aRef.Name.StartsWith("System"))
{
AssemblyName aName=new AssemblyName();
aName.Name=aRef.Name;
Assembly a=rs.GetAssembly(aName);
if (a!=null)
{
Type[] types=a.GetTypes();
foreach (Type t in types)
{// this MessageBox added to
understand what's happening at design time The problem occurs at this
point
MessageBox.Show(t.Name +" is
derived from BaseClass: " +
t.IsSubclassOf(typeof(BaseClass)).ToString());
if
(t.IsSubclassOf(typeof(BaseClass)))

lista.Items.Add(t.FullName);
}
}
}
}
}
try
{
lista.SelectedIndexChanged +=new
EventHandler(lista_SelectedIndexChanged);
edSvc.DropDownControl(lista);
return lista.SelectedItem;
}
catch
{
return value;
}
finally
{
lista.Dispose();
}
return value;
}

private void lista_SelectedIndexChanged(object sender,
EventArgs e)
{
if (edSvc != null) edSvc.CloseDropDown();
}

}
}
-----------------------------------------------------------------------------------------------------------
Finally there is the assembly MyTestControl which defines the
TestControl UserControl (a very simple control containing only a
TextBox and a string property which uses MyEditor as UITypeEditor) and
references MyTypeEditor:

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Drawing.Design;
using TestListConverter;

namespace MyTestControl
{
public class TestControl : System.Windows.Forms.UserControl
{
private String ps;

[Editor(typeof(UnEditor),typeof(UITypeEditor))]
public String s
{
get {return ps;}
set {ps = value;}
}

private System.Windows.Forms.TextBox textBox1;
private System.ComponentModel.Container components = null;

public TestControl()
{
InitializeComponent();
}

protected override void Dispose( bool disposing )
{
if( disposing )
{
if( components != null )
components.Dispose();
}
base.Dispose( disposing );
}

private void InitializeComponent()
{
this.textBox1 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
this.textBox1.Location = new System.Drawing.Point(24,
16);
this.textBox1.Name = "textBox1";
this.textBox1.TabIndex = 0;
this.textBox1.Text = "textBox1";
this.Controls.Add(this.textBox1);
this.Name = "TestControl";
this.Size = new System.Drawing.Size(144, 56);
this.ResumeLayout(false);
}
}
}

---------------------------------------------------------------------------------------------------

At this point I open a new Windows Application Project with references
to MyBaseClass and MyTestControl. At this point if I FIRST add a
reference to MyDerivedClasses, and THEN add a TestControl to the form
everything seems to work fine when I try to set te s property of the
control using the editor. If I change the order of these steps (i.e. I
FIRST add the control, and THEN the reference) DerivedA and DerivedB
appear not to be derived from BaseClass.

Any idea?

Thanks again.

Francesco.

Jan 18 '06 #8
Paguro Bernardo wrote:

<snip>
At this point I open a new Windows Application Project with references
to MyBaseClass and MyTestControl. At this point if I FIRST add a
reference to MyDerivedClasses, and THEN add a TestControl to the form
everything seems to work fine when I try to set te s property of the
control using the editor. If I change the order of these steps (i.e. I
FIRST add the control, and THEN the reference) DerivedA and DerivedB
appear not to be derived from BaseClass.

Any idea?


Hmm.. I wouldn't like to say for sure, to be honest. I suspect if you
delve deeper (using MessageBox.Show as a poor man's debugger) you'll
find it's loading the assembly containing BaseClass from different
places. However, I would suggest that as you've got a workaround, you
use that. It's probably simpler than trying to code around the problem.
Sorry not to give a more pleasant answer :(

Jon

Jan 18 '06 #9

Jon Skeet [C# MVP] ha scritto:

Hmm.. I wouldn't like to say for sure, to be honest. I suspect if you
delve deeper (using MessageBox.Show as a poor man's debugger) you'll
find it's loading the assembly containing BaseClass from different
places. However, I would suggest that as you've got a workaround, you
use that. It's probably simpler than trying to code around the problem.
Sorry not to give a more pleasant answer :(

I investigated a little more, but wasn't able to understand what's
happening. Since we are developing a framework which will be used by 50
programmers, it's quite important to have something which is always
working in the same way and not depending on the order in which things
are done. So I found out that if I don't pass the type of the
superclass directly to IsSuperclassOf, but instead use
ITypeResolutionService to get the assembly and then the type starting
from their names, everything seems to be OK. I don't like it too much,
but it can be considered accettable until I understand better were the
assemblies really come from.

Thanks for your help.

Francesco.

Jan 19 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

14
by: Jim Hubbard | last post by:
Are you up to speed on the difficulties in using the 1.1 .Net framework? Not if you are unaware of the 1,596 issues listed at KBAlertz (http://www.kbalertz.com/technology_3.aspx). If you are...
2
by: ME | last post by:
It appears that IsSubclassOf does not work. In the following example, why does typeof(IDerived).IsSubclassOf(typeof(IRoot)); yeild False when the IDerived interface DOES in fact derive from...
1
by: 3f | last post by:
Hello; We have made a web application that people can download from our web site and installed on: Windows XP Windows 2000 Professional Windows 2003 Server Windows 2000 Server
5
by: Corky | last post by:
This works: db2 SELECT DISTINCT PROBLEM_OBJECTS.PROBLEM_ID FROM PROBLEM_OBJECTS INNER JOIN PROBLEMS ON PROBLEM_OBJECTS.PROBLEM_ID = PROBLEMS.PROBLEM_ID WHERE INTEGER(DAYS(CURRENT DATE) -...
10
by: BBFrost | last post by:
We just recently moved one of our major c# apps from VS Net 2002 to VS Net 2003. At first things were looking ok, now problems are starting to appear. So far ... (1) ...
3
by: thomas | last post by:
Hi, I have three assemblies. In Assembly1 I define an abstract base class called MyBaseClass. In Assembly2 I derive a class from this MyBaseClass. If I asked in the derived class if this class...
1
by: Mark R. Dawson | last post by:
A while ago there was a post where someone asked how to find if a type was derived from another type, three ways were mentioned: Solution1:...
0
by: Rob | last post by:
Hello, I'm new to C# and have a question regarding factoring through reflection. I have a database filled with data represented by name and value pairs. Each name has a identically named...
0
by: Sergistm | last post by:
Hello World, :D I have a problem that it is making me crazy, I hope you can help me. I'm trying to execute a .exe file with the Procces.Start, and there is no problem when the file is on my...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.