How to handle inheritance from two similar sub-classes? - class

I've used the first two videos in this series to learn about some basic OOP concepts.
Lately, I primarily write in Node, so I'm working with prototypical inheritance on the front-end and back-end. However, these tutorials showcase OOP concepts with Java. Java is a strictly-typed language which utilizes classical inheritance.
This question pertains to both classical and prototypical inheritance, but in different ways.
This problem is a little bit difficult to put into words, so I'll use an example:
I've created a super-class called animal. I then create two sub-classes of animal: horse and donkey. Now my program requires a hybrid of the two sub-classes. Creating a mule actually seems to be a little tricky.
At first the answer seemed obvious; create a stand-alone mule sub-class. But that kind of defeats the purpose of OOP. Creating a new sub-class when I already have the traits is a violation of the DRY principle.
To confirm that this is an appropriate way to create my mule I asked myself two questions:
1) Is a mule a horse?
2) Is a mule a donkey?
The answer seemed to be a resounding kind of that leans towards a yes.
I'm completely lost as to how this would be accomplished with classical inheritance. I could not come up with what I considered a "good" solution with interfaces or abstract classes.
In a language which use prototypical inheritance like JavaScript, I might "selectively breed" a mule by pulling down only the methods and instance variables that applied to a mule. However, this seems to be rather close to creating a brand-new sub-class.
What is the "correct" way to handle this problem in both classical and prototypical inheritance?

The concept you are looking for is traits (you actually mentioned it). I will use a different example, that I find more appropriate:
trait Engine {
public function startEngine() {
echo 'Vrooom';
}
}
trait Saddle {
public function rideOnSaddle() {
echo 'I feel the wind';
}
}
interface Vehicle {
public function go();
}
class Car extends Vehicle {
use Engine;
public function go() {
echo $this->startEngine();
}
}
class Bike extends Vehicle {
use Saddle;
public function go() {
echo $this->rideOnSaddle();
}
}
class Motorcycle extends Vehicle {
use Engine;
use Saddle;
public function go() {
echo $this->startEngine();
echo $this->rideOnSaddle();
}
}
Further reading: Traits in PHP, Traits in Javascript.

At first the answer seemed obvious; create a stand-alone mule sub-class.
But that kind of defeats the purpose of OOP. Creating a new sub-class
when I already have the traits is a violation of the DRY principle.
Decomposition might help reaching the DRY goal.
Every behavior/role that not obviously should be inherited, might be considered of being implemented as mixin or trait.
Thus theirs code reuse at different places at class level is much easier and more elegant now via composition.
As for JavaScript, there is only delegation. Inheritance at one hand is supported by an implicit delegation automatism
via the prototype chain, whereas composition gets achieved by delegating functionality explicitly via call or apply.
This makes things much easier since one only needs to deal with objects/instances and methods/function-objects. The class/inheritance
part in JavaScript is covered by either constructor functions and every constructor function's prototype or by (blueprint-)objects that
are passed as prototypes to Object.create. Factories will be useful in providing an API and hiding the preferred implementation of one
of the above mentioned approaches.
Nevertheless the core principles remain untouched with both of them ... dealing with a) objects and function-objects
with b) inheritance and with c) composition.
The following provided example therefore chooses just ECMAScript-3 features and constructor functions. From there it can
be easily transferred(/transpiled) to either class syntax or Object.create.
The OP's example is well chosen, for a mule is neither a horse nor a donkey. It still does belong to the genus Equus but features
its very own chromosome pairs that are distinct from the one of horses or donkeys. Yet it features behavior and visible markers
of both of them. Inheritance therefore, if at all, is achieved via the Equus. Other behavior and appearance that is either specific
or generic to each of both species just will be mixed into a mule.
Function based mixins / traits / talents in JavaScript always get applied to objects/instances, thus even behavior that will be inherited
via the prototype chain, can be collected into such functionality that again can be applied to a prototypal object if necessary/appropriate.
The following example makes use of this technique and also does comment on it in order to demonstrate DRY-ness and code reuse
at this 2 delegation levels of JavaScript.
var
INITIAL_STATES_CONFIG = {
equus: {
specifics: {
type: "equus"
}/*,
generics: {
}*/
},
horse: {
specifics: {
type: "horse"
}/*,
generics: {
}*/
},
donkey: {
specifics: {
type: "donkey"
}/*,
generics: {
}*/
},
mule: {
specifics: {
type: "mule"
}/*,
generics: {
}*/
}
};
function withToeltGait() { // function based mixin/trait/talent.
this.toelt = function () {
return "... tölt ...";
};
return this;
}
function withEquusGenerics(/* state */) { // function based mixin/trait/talent composite.
var
equus = this;
// implementation of equus generics.
equus.walk = function () {
return "... walk ...";
};
equus.trot = function () {
return "... trot ...";
};
equus.gallop = function () {
return "... gallop ...";
};
withToeltGait.call(equus); // composition: use/apply specific equus trait.
return equus;
}
function withEquusSpecifics(state ) { // function based mixin/trait/talent.
var
equus = this;
// implementation of equus specifics.
equus.valueOf = function () {
return Object.assign({}, state);
};
equus.toString = function () {
return JSON.stringify(state);
};
return equus;
}
function Equus(state) { // constructor, kept generic via mixin/trait/talent composition.
state = ((typeof state === 'object') && state) || {};
var
equus = this;
withEquusSpecifics.call(equus, state); // composition: use/apply specific equus trait.
return equus;
}
// equus inheritance via trait based generic equus composite object.
Equus.prototype = withEquusGenerics.call(new Equus/*, state */);
console.log("Equus.prototype.valueOf() : ", Equus.prototype.valueOf());
console.log("Equus.prototype.toString() : ", Equus.prototype.toString());
console.log("Equus.prototype.walk() : ", Equus.prototype.walk());
console.log("Equus.prototype.trot() : ", Equus.prototype.trot());
console.log("Equus.prototype.toelt() : ", Equus.prototype.toelt());
console.log("Equus.prototype.gallop() : ", Equus.prototype.gallop());
console.log("\n");
var equus = new Equus(INITIAL_STATES_CONFIG.equus.specifics);
console.log("equus.valueOf() : ", equus.valueOf());
console.log("equus.toString() : ", equus.toString());
console.log("equus instanceof Equus ? ", (equus instanceof Equus));
console.log("+++ +++ +++\n\n");
function withHorseGenerics(/* state */) { // function based mixin/trait/talent.
/*
implementation of horse generics.
*/
var
horse = this;
// almost all of today's horse breeds lost theirs genetic tölt predisposition.
horse.toelt = function () {};
horse.alwaysAlertedAndFleeQuickly = function () {
return "... always alerted and flee quickly ...";
};
return horse;
}
function withHorseSpecifics(/* state */) { // function based mixin/trait/talent.
/*
implementation of horse specifics.
*/
return this;
}
function Horse(state) { // constructor, kept generic via mixin/trait/talent composition.
state = ((typeof state === 'object') && state) || {};
var
horse = this;
Equus.call(horse, state); // - fulfilling proper equus composition.
withHorseSpecifics.call(horse/*, state */); // - composition: use/apply specific horse trait.
return horse;
}
// equus inheritance together with generic horse trait composition.
Horse.prototype = withHorseGenerics.call(new Equus/*, state */);
var horse = new Horse(INITIAL_STATES_CONFIG.horse.specifics);
console.log("horse.valueOf() : ", horse.valueOf());
console.log("horse.toString() : ", horse.toString());
console.log("horse instanceof Horse ? ", (horse instanceof Horse));
console.log("horse instanceof Equus ? ", (horse instanceof Equus));
console.log("horse.walk() : ", horse.walk());
console.log("horse.trot() : ", horse.trot());
console.log("horse.toelt() : ", horse.toelt());
console.log("horse.gallop() : ", horse.gallop());
console.log("horse.alwaysAlertedAndFleeQuickly() : ",
(horse.alwaysAlertedAndFleeQuickly && horse.alwaysAlertedAndFleeQuickly())
);
console.log("horse.beAttentiveCalculateAndRatherFight() : ",
(horse.beAttentiveCalculateAndRatherFight && horse.beAttentiveCalculateAndRatherFight())
);
console.log("\n");
var toeltingHorse = new Horse(INITIAL_STATES_CONFIG.horse.specifics);
withToeltGait.call(toeltingHorse);
console.log("toeltingHorse.valueOf() : ", toeltingHorse.valueOf());
console.log("toeltingHorse instanceof Horse ? ", (toeltingHorse instanceof Horse));
console.log("toeltingHorse instanceof Equus ? ", (toeltingHorse instanceof Equus));
console.log("toeltingHorse.toelt() : ", toeltingHorse.toelt());
console.log("+++ +++ +++\n\n");
function withDonkeyGenerics(/* state */) { // function based mixin/trait/talent.
/*
implementation of donkey generics.
*/
var
donkey = this;
// donkey breeds, as far as I know, still have the genetic
// predisposition for tölt, but they need to get trained.
//
// donkey.toelt = function () {};
donkey.beAttentiveCalculateAndRatherFight = function () {
return "... be attentive, calculate and rather fight ...";
};
return donkey;
}
function withDonkeySpecifics(/* state */) { // function based mixin/trait/talent.
/*
implementation of donkey specifics.
*/
return this;
}
function Donkey(state) { // constructor, kept generic via mixin/trait/talent composition.
state = ((typeof state === 'object') && state) || {};
var
donkey = this;
Equus.call(donkey, state); // - fulfilling proper equus composition.
withDonkeySpecifics.call(donkey/*, state */); // - composition: use/apply specific donkey trait.
return donkey;
}
// equus inheritance together with generic donkey trait composition.
Donkey.prototype = withDonkeyGenerics.call(new Equus/*, state */);
var donkey = new Donkey(INITIAL_STATES_CONFIG.donkey.specifics);
console.log("donkey.valueOf() : ", donkey.valueOf());
console.log("donkey.toString() : ", donkey.toString());
console.log("donkey instanceof Donkey ? ", (donkey instanceof Donkey));
console.log("donkey instanceof Equus ? ", (donkey instanceof Equus));
console.log("donkey.walk() : ", donkey.walk());
console.log("donkey.trot() : ", donkey.trot());
console.log("donkey.toelt() : ", donkey.toelt());
console.log("donkey.gallop() : ", donkey.gallop());
console.log("donkey.alwaysAlertedAndFleeQuickly() : ",
(donkey.alwaysAlertedAndFleeQuickly && donkey.alwaysAlertedAndFleeQuickly())
);
console.log("donkey.beAttentiveCalculateAndRatherFight() : ",
(donkey.beAttentiveCalculateAndRatherFight && donkey.beAttentiveCalculateAndRatherFight())
);
console.log("+++ +++ +++\n\n");
function withMuleGenerics(/* state */) { // function based mixin/trait/talent composite.
/*
implementation of mule generics.
*/
var
mule = this;
withDonkeyGenerics.call(mule/*, state */); // composition: use/apply generic donkey trait.
/*
add or delete mule generic properties afterwards.
*/
withHorseGenerics.call(mule/*, state */); // composition: use/apply generic horse trait.
/*
add or delete mule generic properties afterwards.
*/
// a mules genetic predisposition for tölt is inherited by its mother horse.
// therefore via calling `withHorseGenerics` this trait gets disabled too by default.
// when facing danger a mule behaves like a donkey; it rather will fight than flee.
mule.alwaysAlertedAndFleeQuickly = function () {};
return mule;
}
function withMuleSpecifics(/* state */) { // function based mixin/trait/talent composite.
/*
implementation of mule specifics.
*/
var
mule = this;
withDonkeySpecifics.call(mule/*, state */); // composition: use/apply specific donkey trait.
/*
add or delete mule specific properties afterwards.
*/
withHorseSpecifics.call(mule/*, state */); // composition: use/apply specific horse trait.
/*
add or delete mule specifics properties afterwards.
*/
return mule;
}
function Mule(state) { // constructor, kept generic via mixin/trait/talent composition.
state = ((typeof state === 'object') && state) || {};
var
mule = this;
Equus.call(mule, state); // - fulfilling proper equus composition.
withMuleSpecifics.call(mule/*, state */); // - composition: use/apply specific mule trait.
return mule;
}
// equus inheritance together with generic mule trait composition.
Mule.prototype = withMuleGenerics.call(new Equus/*, state */);
var mule = new Mule(INITIAL_STATES_CONFIG.mule.specifics);
console.log("mule.valueOf() : ", mule.valueOf());
console.log("mule.toString() : ", mule.toString());
console.log("mule instanceof Mule ? ", (mule instanceof Mule));
console.log("mule instanceof Equus ? ", (mule instanceof Equus));
console.log("mule instanceof Donkey ? ", (mule instanceof Donkey));
console.log("mule instanceof Horse ? ", (mule instanceof Horse));
console.log("mule.walk() : ", mule.walk());
console.log("mule.trot() : ", mule.trot());
console.log("mule.toelt() : ", mule.toelt());
console.log("mule.gallop() : ", mule.gallop());
console.log("mule.alwaysAlertedAndFleeQuickly() : ",
(mule.alwaysAlertedAndFleeQuickly && mule.alwaysAlertedAndFleeQuickly())
);
console.log("mule.beAttentiveCalculateAndRatherFight() : ",
(mule.beAttentiveCalculateAndRatherFight && mule.beAttentiveCalculateAndRatherFight())
);
console.log("\n");
var toeltingMule = new Mule(INITIAL_STATES_CONFIG.mule.specifics);
withToeltGait.call(toeltingMule);
console.log("toeltingMule.valueOf() : ", toeltingMule.valueOf());
console.log("toeltingMule instanceof Mule ? ", (toeltingMule instanceof Mule));
console.log("toeltingMule instanceof Equus ? ", (toeltingMule instanceof Equus));
console.log("toeltingMule.toelt() : ", toeltingMule.toelt());
console.log("+++ +++ +++\n\n");
side note - recommended resources on functions based Mixins / Traits / Talents in JavaScript
A fresh look at JavaScript Mixins by Angus Croll from May 2011
The many talents of JavaScript for generalizing Role Oriented Programming approaches like Traits and Mixins from April 2014.
Additionally I do recommend reading some of the listed answers of mine given on SO, that are related to this topic too.
Traits in javascript
How to use mixins properly in Javascript
ES 6 Classes - Mixins

Related

Java: Mapping DTOs hierarchy using MapStruct

I have Pet, Dog and Cat entity classes. Dog and Cat classes extend Pet.
Also I have PetDTO, DogDTO and CatDTO annotated with #JsonSubtype so Jackson resolves well the class of the dtos.
I want to write a mapper using MapStruct that takes a PetDTO entity (can be a DogDTO or a CatDTO) and returns a Dog or a Cat.
For me in this case, the main goal of using a mapping library is to avoid awful code using instanceof.
Any idea? Thanks!
Not currently possible out-of-the-box - see this ticket in mapstruct's GitHub: #366 Support for abstract class mapping or classes with base class. You can try to push it there or maybe contribute this feature yourself. Looks like a reasonable feature to ask for.
I guess that with the current state of affairs this is your best option:
#Mapper
public interface PetMapper {
default PetDTO toPetDto(Pet pet) {
if (pet instanceof Dog) {
return toDogDTO((Dog) pet);
}
if (pet instanceof Cat) {
return toCatDTO((Cat) pet);
}
throw new IllegalArgumentException("Unknown subtype of Pet");
}
default Pet toPetEntity(PetDTO petDTO) {
if (petDTO instanceof DogDTO) {
return toDogEntity((DogDTO) petDTO);
}
if (petDTO instanceof CatDTO) {
return toCatEntity((CatDTO) petDTO);
}
throw new IllegalArgumentException("Unknown subtype of PetDTO");
}
DogDTO toDogDTO(Dog dog);
Dog toDogEntity(DogDTO dogDTO);
CatDTO toCatDTO(Cat cat);
Cat toCatEntity(CatDTO catDTO);
}
The way I ended up implementing a Mapper for a similar case as above was using a combination of a switch-type, with MapStruct Update Existing and creation Mappers.
In my case a property on the source object dictated the subclass we had to generate.
I initially had different mappers for each subtype, but the duplication of the common mapped properties just seemed wrong. So I came up with the following, leveraging the ability of MapStruct to use updating mappers in order to tackle the common parent type properties:
import org.mapstruct.*;
#Mapper
#Named("QualifierPetMapper")
public interface PetMapper {
#Named("DelegatingPetMapper")
#BeanMapping(ignoreByDefault = true)
default PetTarget mapPet(PetSource petSource) {
switch (petSource.getPetType()) {
case "DOG":
DogTarget dogTarget = mapDog(petSource);
updatePet(dogTarget, petSource);
return (dogTarget);
case "CAT":
CatTarget catTarget = mapCat(petSource);
updatePet(catTarget, petSource);
return (catTarget);
default:
throw new CustomException("Unsupported Pet type: "+ petSource.getPetType());
}
}
#BeanMapping(ignoreByDefault = true)
// Specific mappings for Dog
#Mapping(target = "dogfood.name", source = "dogfoodName")
DogTarget mapDog(PetSource petSource);
#BeanMapping(ignoreByDefault = true)
// Specific mappings for Cat
#Mapping(target = "fish.name", source = "favoriteFish")
CatTarget mapCat(PetSource petSource);
#Named("RootPetMapper")
#BeanMapping(ignoreByDefault = true)
// Common properties for Pet
#Mapping(target = "weight.value", source = "weightValue")
#Mapping(target = "name.value", source = "petName")
#Mapping(target = "color", source = "mainColor")
void updatePet(#MappingTarget PetTarget petTarget, PetSource petSource);
}

Functional Programming in Java 8

As for as I have understood that functional Programming means to give a different behavor implementations interface. Would that be better than I had to create a new Class and implemented that interface in it?
I am not clear on this
interface worldGreeting {
String processName(String str);
}
public class ReadJson {
public static void main(String[] argv) throws Exception {
worldGreeting morningGreeting = (str) -> "Good Morning " + str + "!";
worldGreeting eveningGreeting = (str) -> "Good Evening " + str + "!";
System.out.println(morningGreeting.processName("Waseem"));
System.out.println(eveningGreeting.processName("Saeed"));
}
}
Second approach would be like this
class Moring implements worldGreeting{
#Override
public String processName(String str) {
return "Good Morning " + str + "!";
}
}
class Evening implements worldGreeting{
#Override
public String processName(String str) {
return "Good Evening " + str + "!";
}
}
The difference between single-abstract-method notation and anonymous interface implementations is immaterial, so in my code examples, I will prefer anonymous interface implementations.
Consider these two different ways to provide similar functionality:
Version 1: Type-level Inheritance
interface Greeter {
abstract String greet(String name);
}
class MorningGreeter implements Greeter {
#Override public String greet(String name) {
return "Good morning, " + name + "!";
}
}
class EveningGreeter implements Greeter {
#Override public String greet(String name) {
return "Good evening, " + name + "!";
}
}
Version 2: Anonymous Implementations
interface Greeter {
abstract String greet(String name);
static Greeter morningGreeter = new Greeter() {
#Override public String greet(String name) {
return "Good morning, " + name + "!";
}
};
static Greeter eveningGreeter = new Greeter() {
#Override public String greet(String name) {
return "Good evening, " + name + "!";
}
};
}
What are some of the differences? Version 1 adds three type-level abstractions, while Version 2 adds only one. Furthermore, Version 1 allows any number of MorningGreeters and EveningGreeters to be instantiated, whereas Version 2 is written so that there is exactly one morningGreeter and exactly one eveningGreeter.
I prefer Version 2 for a few reasons.
For one, there's no reason to ever make more than one instance of MorningGreeter, since any two instances will function indistinguishably from one another: the only difference will be their memory address. I try to only ever make classes for things that I will instantiate many times and with different properties.
Second, I personally don't think that MorningGreeter and EveningGreeter should be their own type-level abstractions, since they do not add any methods or fields to Greeter. I try to limit my type-level abstractions by the methods and fields they support, since the purpose of the type system is to prevent you from calling the wrong methods on objects that might not support it, and Greeter is the type-level abstraction for objects that have a single method with signature String greet(String name). I don't feel there is much value in creating two new type-level abstractions with the exact same methods.
Third, Version 2 presents a clear entry point for users of this (very simple) library. In Version 1, users either need to grep all the project files for "implements Greeter" or use IDE magic to jump to the implementing classes. In Version 2, users simply create a greeter with either of the two static convenience methods.
I hope this answers your question. I think it's a good question, more than just a matter of personal taste.

How to resolve generic type at runtime

I'm trying to build a command processor that can take any command that implements a marker interface (or maybe descends from a base class). The processor will handle the command that it is asked to process. However I'm struggling with resolving the true generic type as Resolve(Type) returns an object.
I'm not sure is how to cast this if at all possible?
public void Process(ICommand command)
{
var c = command.GetType();
var t = typeof(ICommandHandler<>).MakeGenericType(new[] { c });
var o = container.Resolve(t);
//((ICommandHandler)o).Handle(command); *** This doesn't work
}
The calling code would be something like this -
Dispatcher.Process(new SomeCommand(Guid.NewGuid(),"Param1",12345));
If you absolutely have to call the ICommandHandler<T>.Handle method and you have no other control over the design of the system, then reflection may be your only choice. There's no great way to deal with the switch from generic to non-generic.
Otherwise, you may have a couple of options.
First, if your Dispatcher.Process can be made generic, you can save all the casting.
public static class Dispatcher
{
public static void Process<T>(T command) where T : ICommand
{
var handler = container.Resolve<ICommandHandler<T>>();
handler.Handle(command);
}
}
This is a pretty common solution to a problem like this that I've seen out in the wild.
If you can't do that, then you may be able to make your ICommandHandler<T> interface implement a non-generic ICommandHandler base interface.
public interface ICommandHandler
{
void Handle(ICommand command);
}
public interface ICommandHandler<T> : ICommandHandler
{
void Handle(T command);
}
In this latter case you'd have to switch your strongly-typed command handler implementations to call the same internal logic for generic or basic handling or you'll get different handling based on the call, which would be bad:
public class SomeCommandHandler : ICommandHandler<SomeCommand>
{
public void Handle(ICommand command)
{
var castCommand = command as SomeCommand;
if(castCommand == null)
{
throw new NotSupportedException("Wrong command type.");
}
// Hand off to the strongly-typed version.
this.Handle(castCommand);
}
public void Handle(SomeCommand command)
{
// Here's the actual handling logic.
}
}
Then when you resolve the strongly-typed ICommandHandler<T> your cast down to ICommandHandler (as shown in your question's sample code) will work.
This is also a pretty common solution, but I've seen it more in systems that existed before generics were available where an updated API was being added.
However, in all cases here, the problem really isn't that Autofac is returning an object; it's a class/type design problem that affects any generic-to-non-generic conversion scenario.
Using Reflection - but is this the best way to approach this?
public void Process(Command command)
{
var c = command.GetType();
var ot = typeof(ICommandHandler<>);
var type = ot.MakeGenericType(new[] { c });
var mi = type.GetMethod("Handle");
var o = container.Resolve(type);
mi.Invoke(o, new object[] { command });
}

Resolving a collection of services from a service type

I have a rather complex bit of resolving going on in Autofac. Basically I want all the objects in the container which implement a specifically named method with a specific argument type. I have implemented some somewhat insane code to get it for me
var services = (from registrations in _componentContext.ComponentRegistry.Registrations
from service in registrations.Services
select service).Distinct();
foreach (var service in services.OfType<Autofac.Core.TypedService>())
{
foreach (var method in service.ServiceType.GetMethods().Where(m => m.Name == "Handle"
&& m.GetParameters().Where(p => p.ParameterType.IsAssignableFrom(implementedInterface)).Count() > 0))
{
var handler = _componentContext.Resolve(service.ServiceType);
method.Invoke(handler, new Object[] { convertedMessage });
}
}
My problem arises in that the handler returned the the resolution step is always the same handler and I cannot see a way to resolve a collection of the the registrations which are tied to the service as one might normally do with container.Resolve>().
I feel like I'm pushing pretty hard against what AutoFac was designed to do and might do better with a MEF based solution. Is there an easy AutoFac based solution to this issue or should I hop over to a more composition based approach?
G'day,
In MEF you could use 'Method Exports' for this (http://mef.codeplex.com/wikipage?title=Declaring%20Exports) but that might be a bit drastic. There are a couple of ways to achieve what you want in Autofac.
You can make the above code work by searching for registrations rather than services:
var implementorMethods = _componentContext.ComponentRegistry.Registrations
.Select(r => new {
Registration = r,
HandlerMethod = r.Services.OfType<TypedService>()
.SelectMany(ts => ts.ServiceType.GetMethods()
.Where(m => m.Name == "Handle" && ...))
.FirstOrDefault()
})
.Where(im => im.HandlerMethod != null);
foreach (var im in implementorMethods)
{
var handler = _componentContext.ResolveComponent(im.Registration, new List<Parameter>());
im.HandlerMethod.Invoke(handler, new object[] { convertedMessage });
}
I.e. implementorMethods is a list of the components implementing a handler method, along with the method itself. ResolveComponent() doesn't rely on a service to identify the implementation, so there's no problem with the service not uniquely identifying a particular implementor.
This technique in general will probably perform poorly (if perf is a concern here) but also as you suspect will work against the design goals of Autofac (and MEF,) eliminating some of the benefits.
Ideally you need to define a contract for handlers that will let you look up all handlers for a message type in a single operation.
The typical recipe looks like:
interface IHandler<TMessage>
{
void Handle(TMessage message);
}
Handlers then implement the appropriate interface:
class FooHandler : IHandler<Foo> { ... }
...and get registered at build-time like so:
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(typeof(FooHandler).Assembly)
.AsClosedTypesOf(typeof(IHandler<>));
To invoke the handlers, define a message dispatcher contract:
interface IMessageDispatcher
{
void Dispatch(object message);
}
...and then its implementation:
class AutofacMessageDispatcher : IMessageDispatcher
{
static readonly MethodInfo GenericDispatchMethod =
typeof(AutofacMessageDispatcher).GetMethod(
"GenericDispatch", BindingFlags.NonPublic | BindingFlags.Instance);
IComponentContext _cc;
public AutofacMessageDispatcher(IComponentContext cc)
{
_cc = cc;
}
public void Dispatch(object message)
{
var dispatchMethod = GenericDispatchMethod
.MakeGenericMethod(message.GetType());
dispatchMethod.Invoke(this, new[] { message });
}
void GenericDispatch<TMessage>(TMessage message)
{
var handlers = _cc.Resolve<IEnumerable<IHandler<TMessage>>>();
foreach (var handler in handlers)
handler.Handle(message);
}
}
...which is registered like so:
builder.RegisterType<AutofacMessageDispatcher>()
.As<IMessageDispatcher>();
The component that feeds in the messages will then resolve/use IMessageDispatcher to get the messages to the handlers.
var dispatcher = _cc.Resolve<IMessageDispatcher>();
dispatcher.Dispatch(message);
There are still ways to do this without the interface, but all rely on creating some kind of contract that uniquely defines handlers for a particular message (e.g. a delegate.)
In the long run the generic handler pattern will be the easiest to maintain.
Hope this helps, Nick.

asp.net MVC 2 - most elegant way of isolating guard code - guarding against null controller parameters

I have a very simple problem, but I'm looking for the 'best' solution to the following:
I have multiple controller actions something like this:
public ActionResult DoSomething(PackageViewModel packageByName, DoSomethingInputModel inputModel)
{
if (packageByName == null)
{
Response.StatusCode = 404;
Response.StatusDescription = "Package not found : " + RouteData.GetRequiredString("packageName");
return View("Error");
}
...
What is the best way to isolate this cross cutting concern?
I can make a function
I can use an AOP tool like PostSharp
ActionFilter
Other?
In fact ActionFilter is an AOP. Write your own ActionFilter implementation to chceck if parameter is not null. If you always need to check the same thing on the beggining of your controller execution then it's the best way. It's easy to write, resusable in whole application and very MVC 2.
Here's what I implemented (based on #ŁukaszW.pl answer)
Hopefully this will save someone some time.
public class GuardAgainstNullPackage : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
BookingController controller = ((BookingController)filterContext.Controller);
if (filterContext.ActionParameters["packageByName"] == null || !(filterContext.ActionParameters["packageByName"] is PackageViewModel))
{
controller.Response.StatusCode = 404;
controller.Response.StatusDescription = "Package not found : " + filterContext.RouteData.GetRequiredString("packageName");
filterContext.Result = new ViewResult() { ViewName = "Error" };
}
base.OnActionExecuting(filterContext);
}
}