Reputation: 2478
I want to decouple Foo
from FooHandler
. Also they should be registered by DI via assembly scanning. Therefore I have 3 types:
interface IFooHandler { // no type arguments, so it can be used by reflection
void DoStuff(object foo);
}
interface IFooHandler<TFoo>: IFooHandler { // TFoo tells us, what foo is it for
void DoStuff(TFoo foo); // developers are happy with strongly typed foos
}
abstract class FooHandler<TFoo>: IFooHandler<TFoo> {
void IFooHandler.DoStuff(object foo){
DoStuff((TFoo)foo); // adapter of interface 2 to 1
}
abstract void DoStuff(TFoo foo); // for nice implementation
}
The problem with such design is that I cannot easly forbid other people in my assembly from using IFooHandler
or IFooHandler<TFoo>
directly. Using first is bad idea, because it will not be registered in DI and it will fail. Using second is bad idea, because you write useless boilerplate, already written in base class.
Is it reasonable, to add Obsolete
attribute with error=True
to prevent people from using these interfaces? Is there is better way to hide them (I cannot move them to another assembly and mark as internal).
Concrete example:
Lets say we have webapplication, and in that panel on various types there are contexts (Foo) that are identify of list of options for given context. Lets say you have currency selection, and Foo is CurrencyList
. Then you have CurrencyListProvider
class, that takes CurrencyList, retrieves available currencies from database and returns to panel, so user can choose which currency he want use for transaction. I am using concrete types, so you may easily move over codebase with tools such as resharper, but inside these concrete types there are string traveling through http.
Upvotes: 0
Views: 166
Reputation: 17658
Is it reasonable, to add Obsolete attribute with error=True to prevent people from using these interfaces?
No. If you are afraid somebody will access your implementation directly, this won't stop them. A side effect is that they will question your skills as developer.
Also they should be registered by DI via assembly scanning
This is where your pain lives. Assembly scanning is just that: check the assembly and create instances, preferably through a nice public constructor. So, if you don't drop this requirement it's going to be... too complicated.
If you where to drop this requirement, and I think you can, since you have 3 versions and need a mechanism to switch between them; consider to use a own factory.
Let your factory decide which version to return.
You could even use friend assemblies to protect the constructors.
the real answer:
I think it's the only logical thing to do and much more descent than marking things as obsolete.
Upvotes: 1