HighTechTalks DotNet Forums  

Access subclass attributes from base

Dotnet Framework (CLR) microsoft.public.dotnet.framework.clr


Discuss Access subclass attributes from base in the Dotnet Framework (CLR) forum.



Reply
 
Thread Tools Search this Thread Display Modes
  #1  
Old   
Kyle M. Burns
 
Posts: n/a

Default Access subclass attributes from base - 12-19-2007 , 11:01 AM






Using the 2.0 framework, I'm trying to flesh out an idea that I had for a
generic factory using an attribute to specify the type of concrete class that
will be implemented. Our base factory does all the work and looks like this:

abstract BaseFactory<TInterface, TConcreteImplementation>
{
static TInterface Instance { get; }
}

With subclasses implemented using code like this:

FBusinessObject : BaseFactory<IBusinessObject, BusinessObject>{}

A big problem with this is that it creates a compile time dependency between
the consumer of the interface and the assembly containing the concrete
implementation. My thought was that if I could change the BaseFactory to
look like this:

abstract BaseFactory<TInterface>
{
static TInterface Instance { get; }
}

and subclasses to look like:

[ConcreteImplementation(typeof(BusinessObject))]
FBusinessObject : BaseFactory<IBusinessObject>{}

then I could have clients of the factory only need to know about the
assembly containing the interface and that containing the factory.

The problem is that I'm not finding a way to access the attributes of the
subclass from within the base class. Any thoughts on how/if this can be done?


Reply With Quote
  #2  
Old   
Jeroen Mostert
 
Posts: n/a

Default Re: Access subclass attributes from base - 12-19-2007 , 05:04 PM






Kyle M. Burns wrote:
Quote:
Using the 2.0 framework, I'm trying to flesh out an idea that I had for a
generic factory using an attribute to specify the type of concrete class that
will be implemented.
Be careful about ultra-genericity. It looks really neat on paper, but when
you're finally done and take a step back you usally find out that you
haven't actually gained any flexibility or safety that you couldn't have
achieved with Plain Old Code, and you've atually saddled your clients with a
big learning curve when they try to understand what the hell is going on
(and they always eventually need to understand what the hell is going on,
since the perfect framework exists only in dreams). I've fallen into this
trap more than once. .NET makes it easy for you by having both generics and
metadata.

Remember that it's totally irrelevant if it's neat in *theory*. A framework
should be offering *practical* benefits. So now we've got the sermon out of
the way, let's look at the actual issues.

Quote:
Our base factory does all the work and looks like this:

abstract BaseFactory<TInterface, TConcreteImplementation
{
static TInterface Instance { get; }
}

Are you omitting the actual factory methods? That doesn't exactly make
things clearer. I'm assuming "Instance" is intended to be the factory
instance, but then that's belied by this:

Quote:
With subclasses implemented using code like this:

FBusinessObject : BaseFactory<IBusinessObject, BusinessObject>{}

Is this class supposed to have an Instance of type "IBusinessObject"? If so,
how is this a factory? "BusinessObject" could implement the singleton
pattern itself. Don't you mean it has to have an Instance field of type
"FBusinessObject"? The *factory* being a singleton would make more sense
(even though there's still no reason why you should decide that all
factories have to be singletons!)

I hope "Instance" isn't supposed to be the thing that returns multiple
different objects! Using a property for that is totally inappropriate.

Quote:
[ConcreteImplementation(typeof(BusinessObject))]
FBusinessObject : BaseFactory<IBusinessObject>{}

then I could have clients of the factory only need to know about the
assembly containing the interface and that containing the factory.

Why do you need to mention "BusinessObject" at all at this point? Isn't the
factory implementation the thing that has to deal with BusinessObjects
eventually? Then let that take care of it and don't hoist this dependency to
the general level, where it doesn't belong.

You seem to have created the problem for yourself by insisting that a
super-generic base class contain it all. This doesn't actually help the
subclasses. For example, how is this base class supposed to know how to
instantiate concrete classes? Haven't you locked yourself into a design
where all objects must have a default constructor or some other "one size
fits all" creation pattern? What's the benefit there, and how would it hurt
subclasses to have to write out that construction themselves?

Quote:
The problem is that I'm not finding a way to access the attributes of the
subclass from within the base class. Any thoughts on how/if this can be done?

You can use Object.GetType() to get the concrete type of the instance, and
Type.GetAttributes() to get the attributes of that type. So:

abstract BaseFactory<...> {
public void Foo() {
ConcreteImplementationAttribute cia = (ConcreteImplementationAttribute)
Attribute.GetCustomAttribute(this.GetType(),
typeof(ConcreteImplementationAttribute));
// Use cia here
}

}

The usual caveats apply: reflection is slow when not carefully applied and
adds to maintenance costs by introducing hidden dependencies. In this case,
it really doesn't seem worth it. You're writing more framework code than
code that actually *does* something, and it doesn't seem to give you
anything in the way of reusability and flexibility. If all you're trying to
do is saving the clients from writing what appears to be one line of code,
don't bother.

--
J.


Reply With Quote
  #3  
Old   
Jeroen Mostert
 
Posts: n/a

Default Re: Access subclass attributes from base - 12-19-2007 , 05:15 PM



Jeroen Mostert wrote:
<snip>
Quote:
You can use Object.GetType() to get the concrete type of the instance,
and Type.GetAttributes() to get the attributes of that type.
Oops, that's Attribute.GetCustomAttribute[s](), of course.

--
J.


Reply With Quote
  #4  
Old   
Kyle M. Burns
 
Posts: n/a

Default Re: Access subclass attributes from base - 12-19-2007 , 05:54 PM



Quote:
Remember that it's totally irrelevant if it's neat in *theory*. A framework
should be offering *practical* benefits. So now we've got the sermon out of
the way, let's look at the actual issues.
We're not talking theory here, but a set of objects that share a common
creation strategy in a distributed COM+ environment where logging and other
corrective measures to ensure the client obtains an instance of the object
need to be taken. The approach originally recommended by Microsoft was a
factory object with the interface described earlier that implements more than
a few lines in the actual factory method and needs to be applied to every one
of our factories.

Quote:
Are you omitting the actual factory methods? That doesn't exactly make
things clearer. I'm assuming "Instance" is intended to be the factory
instance, but then that's belied by this:
I was only including the interface definition to keep the post focused on
what's important. The Instance property is the factory method that utilizes
the generic information to create and return an instance of
TConcreteImplementation conforming to TInterface. It would be more
appropriate to have this be a GetInstance() method instead of a property, but
that in no way affects the functionality.

Quote:
Why do you need to mention "BusinessObject" at all at this point? Isn't the
factory implementation the thing that has to deal with BusinessObjects
eventually? Then let that take care of it and don't hoist this dependency to
the general level, where it doesn't belong.
The subclasses only responsibility is to tell the base class to which
interface Instance must conform and which concrete class will be used in the
creation, so this is the only point in the creation process in which
BusinessObject matters at all.

Quote:
You can use Object.GetType() to get the concrete type of the instance, and
Type.GetAttributes() to get the attributes of that type.
I was trying to find a way to accomplish this from the static factory
method, but it looks like I may need "this" in order to obtain the attributes.


"Jeroen Mostert" wrote:

Quote:
Kyle M. Burns wrote:
Using the 2.0 framework, I'm trying to flesh out an idea that I had for a
generic factory using an attribute to specify the type of concrete class that
will be implemented.

Be careful about ultra-genericity. It looks really neat on paper, but when
you're finally done and take a step back you usally find out that you
haven't actually gained any flexibility or safety that you couldn't have
achieved with Plain Old Code, and you've atually saddled your clients with a
big learning curve when they try to understand what the hell is going on
(and they always eventually need to understand what the hell is going on,
since the perfect framework exists only in dreams). I've fallen into this
trap more than once. .NET makes it easy for you by having both generics and
metadata.

Remember that it's totally irrelevant if it's neat in *theory*. A framework
should be offering *practical* benefits. So now we've got the sermon out of
the way, let's look at the actual issues.

Our base factory does all the work and looks like this:

abstract BaseFactory<TInterface, TConcreteImplementation
{
static TInterface Instance { get; }
}

Are you omitting the actual factory methods? That doesn't exactly make
things clearer. I'm assuming "Instance" is intended to be the factory
instance, but then that's belied by this:

With subclasses implemented using code like this:

FBusinessObject : BaseFactory<IBusinessObject, BusinessObject>{}

Is this class supposed to have an Instance of type "IBusinessObject"? If so,
how is this a factory? "BusinessObject" could implement the singleton
pattern itself. Don't you mean it has to have an Instance field of type
"FBusinessObject"? The *factory* being a singleton would make more sense
(even though there's still no reason why you should decide that all
factories have to be singletons!)

I hope "Instance" isn't supposed to be the thing that returns multiple
different objects! Using a property for that is totally inappropriate.

[ConcreteImplementation(typeof(BusinessObject))]
FBusinessObject : BaseFactory<IBusinessObject>{}

then I could have clients of the factory only need to know about the
assembly containing the interface and that containing the factory.

Why do you need to mention "BusinessObject" at all at this point? Isn't the
factory implementation the thing that has to deal with BusinessObjects
eventually? Then let that take care of it and don't hoist this dependency to
the general level, where it doesn't belong.

You seem to have created the problem for yourself by insisting that a
super-generic base class contain it all. This doesn't actually help the
subclasses. For example, how is this base class supposed to know how to
instantiate concrete classes? Haven't you locked yourself into a design
where all objects must have a default constructor or some other "one size
fits all" creation pattern? What's the benefit there, and how would it hurt
subclasses to have to write out that construction themselves?

The problem is that I'm not finding a way to access the attributes of the
subclass from within the base class. Any thoughts on how/if this can be done?

You can use Object.GetType() to get the concrete type of the instance, and
Type.GetAttributes() to get the attributes of that type. So:

abstract BaseFactory<...> {
public void Foo() {
ConcreteImplementationAttribute cia = (ConcreteImplementationAttribute)
Attribute.GetCustomAttribute(this.GetType(),
typeof(ConcreteImplementationAttribute));
// Use cia here
}

}

The usual caveats apply: reflection is slow when not carefully applied and
adds to maintenance costs by introducing hidden dependencies. In this case,
it really doesn't seem worth it. You're writing more framework code than
code that actually *does* something, and it doesn't seem to give you
anything in the way of reusability and flexibility. If all you're trying to
do is saving the clients from writing what appears to be one line of code,
don't bother.

--
J.


Reply With Quote
  #5  
Old   
Jeroen Mostert
 
Posts: n/a

Default Re: Access subclass attributes from base - 12-20-2007 , 01:03 PM



Kyle M. Burns wrote:
Quote:
Remember that it's totally irrelevant if it's neat in *theory*. A framework
should be offering *practical* benefits. So now we've got the sermon out of
the way, let's look at the actual issues.

We're not talking theory here, but a set of objects that share a common
creation strategy in a distributed COM+ environment where logging and other
corrective measures to ensure the client obtains an instance of the object
need to be taken.
In that case, you have my condolences. DCOM is no fun.

Quote:
The approach originally recommended by Microsoft was a
factory object with the interface described earlier that implements more than
a few lines in the actual factory method and needs to be applied to every one
of our factories.

So you have share functionality (actually, it sounds more like *identical*
functionality to me). There are still quite a lot of ways to implement that.

Quote:
Why do you need to mention "BusinessObject" at all at this point? Isn't the
factory implementation the thing that has to deal with BusinessObjects
eventually? Then let that take care of it and don't hoist this dependency to
the general level, where it doesn't belong.
The subclasses only responsibility is to tell the base class to which
interface Instance must conform and which concrete class will be used in the
creation, so this is the only point in the creation process in which
BusinessObject matters at all.

Alright, I have a clearer picture of what you're trying to achieve now.

Quote:
You can use Object.GetType() to get the concrete type of the instance, and
Type.GetAttributes() to get the attributes of that type.
I was trying to find a way to accomplish this from the static factory
method, but it looks like I may need "this" in order to obtain the attributes.

Yes, you will. But there doesn't seem to be any pressing reason to muck
about with attributes. From what I've gathered so far, your base class does
*everything*, including the instantiation, so I gather it has some way of
instantiating a business object given its concrete type. How about:

static class BusinessFactory { // Or make it a singleton
public static IBusinessObject CreateBusinessObject<IBusinessObject,
TBusinessObject>() {
/* Instantiate a new TBusinessObject here, return as IBusinessObject*/
}
};

public class WidgetFactory {
public IWidget CreateWidget() {
return BusinessFactory.CreateBusinessObject<IWidget, Widget>();
}
}

Add interfaces and subtyping where necessary. Since WidgetFactory only uses
the concrete Widget type in its method, not its type signature, there is no
dependency between the clients of WidgetFactory and the Widget. Or are you
worried about some other dependency? It's not completely clear to me. Note
that there is obviously no way to avoid some dependency between
WidgetFactory and Widget, since it will have to pass the type to the
business object factory somehow! If you want to remove *all* compile-time
dependencies, you'd have to use reflection to dynamically get the types, but
this seems far more trouble than it's worth.

--
J.


Reply With Quote
  #6  
Old   
Ben Voigt [C++ MVP]
 
Posts: n/a

Default Re: Access subclass attributes from base - 12-24-2007 , 01:24 PM




"Kyle M. Burns" <KyleMBurns (AT) discussions (DOT) microsoft.com> wrote

Quote:
Using the 2.0 framework, I'm trying to flesh out an idea that I had for a
generic factory using an attribute to specify the type of concrete class
that
will be implemented. Our base factory does all the work and looks like
this:

abstract BaseFactory<TInterface, TConcreteImplementation
{
static TInterface Instance { get; }
}

With subclasses implemented using code like this:

FBusinessObject : BaseFactory<IBusinessObject, BusinessObject>{}

A big problem with this is that it creates a compile time dependency
between
the consumer of the interface and the assembly containing the concrete
implementation. My thought was that if I could change the BaseFactory to
look like this:

abstract BaseFactory<TInterface
{
static TInterface Instance { get; }
}

and subclasses to look like:

[ConcreteImplementation(typeof(BusinessObject))]
FBusinessObject : BaseFactory<IBusinessObject>{}

then I could have clients of the factory only need to know about the
assembly containing the interface and that containing the factory.

The problem is that I'm not finding a way to access the attributes of the
subclass from within the base class. Any thoughts on how/if this can be
done?

Use delegation (not delegates) instead of inheritance. Only inheritance
forces visibility to the client assembly.

static class FactoryHelper
{
static TInstance MakeAnInstance<TInterface, TConcreteImplementation>()
{ ... }
}

public static class FBusinessObject
{
public static IBusinessObject GetInstance() { return
MakeAnInstance<IBusinessObject, BusinessObject>(); }
}

This reduces the duplicated code to a very managable level.

Or maybe combine with delegates and anonymous methods to fit constructor
parameters inside your reusable factory code (I assume logging, registration
with ROT, that sort of thing).




Reply With Quote
Reply




Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Powered by vBulletin Version 3.5.4
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.