We have a class Event (it's actually named differently, but I'm just making abstraction):
public class Event
{
    public string Name { get; set; }
    public string Description { get; set; }
    public EventType EventType { get; set; }
}
We need to build an instance of a Message class with this object, but depending on the EventType, we use a different builder:
switch (event.EventType)
{
    case EventType.First:
        message = FirstMessageBuilder.Build(event);
        break;
    case EventType.Second:
        message = SecondMessageBuilder.Build(event);
        break;
}
Do you think this is acceptable, or should we take the following approach:
Make an abstract class:
public class Event
{
    public string Name { get; set; }
    public string Description { get; set; }
   开发者_如何学运维 public abstract Message BuildMessage();
}
Then derive two classes: class FirstMessage and class SecondMessage and make the domain objects responsible for building the message.
I hope it isn't too abstract. The bottom line is we need to transform one class to another. A simple mapper won't do, because there are properties with XML content and such (due to a legacy application making the events). Just accept what we're trying to do here.
The real question is: can a domain object be responsible for such a transformation, or would you not recommend it? I would avoid the ugly switch statement, but add complexity somewhere else.
Whilst I agree with Thomas, you might want to look at the following design patterns to see if they help you:
- Vistor Pattern
- Double-Dispatch Pattern
- Builder Pattern
Strictly speaking, a domain object shouldn't be responsible for anything other than representing the domain. "Changing type" is clearly a technical issue and should be done by some kind of service class, to maintain a clear separation of concerns...
In order to gain the readability of
var message = eventInstance.AsMessage();
as well following the single responsibility principle, you could define AsMessage() as an extension method of the event type.
There are few possible solutions. To use abstract factory:
public interface IMessageFactory 
{
    Message Create();
}
public class FirstMessageFactory : IMessageFactory
{
    public Message Create()
    {
        //...
    }
}
public class SomeService
{
     private readonly IMessageFactory _factory;
     public SomeService(IMessageFactory factory)
     {
          _factory = factory;
     }
     public void DoSomething() 
     {
         var message = _factory.Create();
         //...
     }
}
Now you can wire IoC container to right factory for requested service.
To use Assembler which makes the transformation:
public interface IAssembler<TSource, TDestination> 
{
    TDestination Transform(TSource source);
}
This is quite similar to factory pattern, but if you are dependent on EventType, its possible to do it like:
public interface IAssembler<TEventType> 
{
    object Transform(object source);
}
I would encapsulate the logic into a separate Factory/Builder class, and use an extension method on Event to call the builder.
This would give you the best of both worlds.
 
         
                                         
                                         
                                         
                                        ![Interactive visualization of a graph in python [closed]](https://www.devze.com/res/2023/04-10/09/92d32fe8c0d22fb96bd6f6e8b7d1f457.gif) 
                                         
                                         
                                         
                                         加载中,请稍侯......
 加载中,请稍侯......
      
精彩评论