Asp.net core 2.0 Conditional DI - asp.net-core-2.0

I have an interface that has 2 implementation
IMYService
MyServiceA
MYServiceB
Here the Implementation is dependent on some data in the request header used by the construtor of the Services like
If Header has value of internalId then use MyServiceA and pass that Id to the services in constructor
while if the value is missing use MyServiceB where as this service construct does not expect id.
My Controller is defined with DI for IMyservice

In general, you need a factory. That's generally a separate class that is responsible to managing instances of a particular similar type of thing and returns the appropriate instance based on some sort of convention or condition. For example, if you've used IHttpClientFactory, you've see one in action.
Since the implementation depends on the request, you can cheat a little by using the "factory" overload of AddScoped:
services.AddScoped<IMyService>(p =>
{
// return either MyServiceA or MyServiceB
});
The p param of the lambda is actually a scoped instance of IServiceProvider, so you can do stuff like pull out IHttpContextAccessor to look at the request details.

Related

Spring Integration support for the Normalizer EIP

Spring Integration here. I was expecting to see a normalize(...) method off the IntegrationFlow DSL and was surprised to find there wasn't one (like .route(...) or .aggregate(...), etc.).
In fact, some digging on Google and the Spring Integration docs, and I can't seem to find any built-in support for the Normalizer EIP. So I've taken a crack at my own:
public class Normalizer extends AbstractTransformer {
private Class<?> targetClass;
private GenericConverter genericConverter;
public Normalizer(Class<?> targetClass, GenericConverter genericConverter) {
Optional<GenericConverter.ConvertiblePair> maybePair = genericConverter.getConvertibleTypes().stream()
.filter(convertiblePair -> !convertiblePair.getTargetType().equals(targetClass))
.findAny();
assert(maybePair.isEmpty());
this.targetClass = targetClass;
this.genericConverter = genericConverter;
}
#Override
protected Object doTransform(Message<?> message) {
Object inbound = message.getPayload();
return genericConverter.convert(inbound, TypeDescriptor.forObject(inbound), TypeDescriptor.valueOf(targetClass));
}
}
The idea is that Spring already provides the GenericConverter SPI for converting multiple source types to 1+ target type instance. We just need a specialized flavor of that that has the same target type for all convertible pairings. So here we extend AbstractTransformer and pass it one of these GenericConverters to use. During initialization we just verify that all the possible convertible pairs convert to the same targetClass specified for the Normalizer.
The idea is I could instantiate it like so:
#Bean
public Normalizer<Fizz> fizzNormalizer(GenericConverter fizzConverter) {
return new Normalizer(Fizz.class, fizzConverter);
}
And then put it in a flow:
IntegrationFlow someFlow = IntegrationFlows.from(someChannel())
.transform(fizzNormalizer())
// other components
.get();
While I believe this will work, before I start using it too heavily I want to make sure I'm not overlooking anything in the Spring Integration framework that will accomplish/satisfy the Normalizer EIP for me. No point in trying to reinvent the wheel and all that jazz. Thanks for any insight.
If you take a closer look into that EI pattern, then you see:
Use a Normalizer to route each message type through a custom Message Translator so that the resulting messages match a common format.
The crucial part of this pattern that it is a composed one with a router as input endpoint and a set of transformers for each inbound message type.
Since it is that kind of component which is data model dependent and more over the routing and transforming logic might differ from use-case to use-case, it is really hard to make an out-of-the-box single configurable component.
Therefore you need to investigate what type of routing you need to do to chose a proper one for input: https://docs.spring.io/spring-integration/docs/current/reference/html/message-routing.html#router
Then for every routed type you nee to implement respective transformer to produce a canonical data mode.
All of the can be just wrapped into a #MessagegingGateway API to hide the normalize behind so-called pattern implementation.
That's what I would do to follow that EI pattern recommendations.
However if your use-case is so simple as just convert from one type to another, so yes, then you can rely on the ConversionService. You register your custom Converter: https://docs.spring.io/spring-integration/docs/current/reference/html/endpoint.html#payload-type-conversion. And then just use a .convert(Class) API from IntegrationFlowDefinition.
But again: since there is no easy way to cover all the possible domain use-cases, we cannot provide an out-of-the-box Normalizer implementation.

DDD: How to refactor (wrap) remote service call into domain?

There is a service class FooService and method named fetchFoos that calls remote service, deserialize the JSON response and returns graph of value objects (starting with root Foo object). For now, there is no other behavior with this remote service, i.e. we are just fetching some 3rd party data. Speaking in DDD terms, this is closed bounded context with sole purpose of providing data, using its own models.
We may leave this method as a service; but... it seems it would be better if we may rename it to something more 'linguistic'.
For example, we could migrate singleton service to a simple bean named: FooFetcher (any better name?) and have method fetchFooForBar() that does the same. Then instead of injecting the service, we would simple create a new instance of this object and use it.
I even think that FooFetcher is a wrong domain name, it should be just Foos and the method would be fetchForBar().
However, some other ppl think that should come from a repository - so basically, we would just need to rename the FooService to FooRepository.
Any collective wisdom on how to encapsulate remote services in DDD?
Assuming Foo is an entity in your bounded context, you can think of this service as an infrastructure service that will be invoked from a repository.
In the following example, I named the fetcher "FooFetchService" and it has a method called "getFoo" return a JSON string with the "contents" of the foo object
public interface FooRepository {
public Foo getById(String fooId);
}
public class RemoteFooRepository implements FooRepository {
#Inject
FooFetchService fooFetchService;
public Foo getById(String fooId) {
String returnedFoo = fooFetchService.getFoo(fooId);
/* add code here to deserialize the JSON contents of the returnFoo variable to an object Foo foo*/
return foo;
}
}
RemoteFooRepository is just an implementation of FooRepository which happens to retrieve a Foo via some remote service. You can inject this in any of your other services classes that need it.

How to use ObjectContext with Model Builder?

Is there a way we can use ObjectContext with DbContext's ModelBuilder? We don't want to use POCO because we have customized property code that does not modify entire object in update, but only update modified properties. Also we have lots of serialisation and auditing code that uses EntityObject.
Since poco does create a proxy with EntityObject, we want our classes to be derived from EntityObject. We don't want proxy. We also heavily use CreateSourceQuery. The only problem is EDMX file and its big connection string syntax web.config.
Is there any way I can get rid of EDMX file? It will be useful as we can dynamically compile new class based on reverse engineering database.
I would also like to use DbContext with EntityObject instead of poco.
Internal Logic
Access Modified Properties in Save Changes which is available in ObjectStateEntry and Save them onto Audit with Old and New Values
Most of times we need to only check for Any condition on Navigation Property for example
User.EmailAddresses.CreateSourceQuery()
.Any( x=> x.EmailAddress == givenAddress);
Access Property Attributes, such as XmlIgnore etc, we rely heavily on attributes defined on the properties.
A proxy for a POCO is a dynamically created class which derives from (inherits) a POCO. It adds functionality previously found in EntityObject, namely lazy loading and change tracking, as long as a POCO meets requirements. A POCO or its proxy does not contain an EntityObject as the question suggests, but rather a proxy contains functionality of EntityObject. You cannot (AFAIK) use ModelBuilder with EntityObject derivatives and you cannot get to an underlying EntityObject from a POCO or a proxy, since there isn't one as such.
I don't know what features of ObjectContext does your existing serialisation and auditing code use, but you can get to ObjectContext from a DbContext by casting a DbContext to a IObjectContextAdapter and accessing IObjectContextAdapter.ObjectContext property.
EDIT:
1. Access Modified Properties in Save Changes which is available in ObjectStateEntry and Save them onto Audit with Old and New Values
You can achieve this with POCOs by using DbContext.ChangeTracker. First you call DbContext.ChangeTracker.DetectChanges to detect the changes (if you use proxies this is not needed, but can't hurt) and then you use DbCotnext.Entries.Where(e => e.State != EntityState.Unchanged && e.State != EntityState.Detached) to get DbEntityEntry list of changed entities for auditing. Each DbEntityEntry has OriginalValues and CurrentValues and the actual Entity is in property Entity.
You also have access to ObjectStateEntry, see below.
2. Most of times we need to only check for Any condition on Navigation Property for example:
User.EmailAddresses.CreateSourceQuery().Any( x=> x.EmailAddress == givenAddress);
You can use CreateSourceQuery() with DbContext by utilizing IObjectContextAdapter as described previously. When you have ObjectContext you can get to the source query for a related end like this:
public static class DbContextUtils
{
public static ObjectQuery<TMember> CreateSourceQuery<TEntity, TMember>(this IObjectContextAdapter adapter, TEntity entity, Expression<Func<TEntity, ICollection<TMember>>> memberSelector) where TMember : class
{
var objectStateManager = adapter.ObjectContext.ObjectStateManager;
var objectStateEntry = objectStateManager.GetObjectStateEntry(entity);
var relationshipManager = objectStateManager.GetRelationshipManager(entity);
var entityType = (EntityType)objectStateEntry.EntitySet.ElementType;
var navigationProperty = entityType.NavigationProperties[(memberSelector.Body as MemberExpression).Member.Name];
var relatedEnd = relationshipManager.GetRelatedEnd(navigationProperty.RelationshipType.FullName, navigationProperty.ToEndMember.Name);
return ((EntityCollection<TMember>)relatedEnd).CreateSourceQuery();
}
}
This method uses no dynamic code and is strongly typed since it uses expressions. You use it like this:
myDbContext.CreateSourceQuery(invoice, i => i.details);

Use interfaces in JAX-WS web methods

I need to use an interface as a parameter and as a return type in a JAX-WS web method. When starting my server I receive an IllegalAnnotationsException, which tells me that JAXB cannot handle interfaces.
I tried to annotate my class, method result and method parameters with #XmlRootElement and #XmlElement(type = ...) respectively, but this does not work.
How can I use an interface as an parameter and as a result type in a JAX-WS web method?
Take a look at #XmlJavaTypeAdapter. Maybe it will do the trick. More information available in here.

Trying to understand IOC and binding

I am very new to concept of IOC and I understand the fact that they help us resolve different classes in different contexts. Your calling class will just interact with Interface and Interface with decide which implementation to give you and it takes care of newing up the object.
Please do correct me if I am understanding is wrong because my question is based on that:
Now, I see this pattern very often in these projects:
private readonly IEmailService emailService;
private readonly ITemplateRenderer templateRenderer;
private readonly IHtmlToTextTransformer htmlToTextTransformer;
public TemplateEmailService(IEmailService emailService,
ITemplateRenderer templateRenderer,
IHtmlToTextTransformer htmlToTextTransformer)
{
this.emailService = emailService;
this.htmlToTextTransformer = htmlToTextTransformer;
this.templateRenderer = templateRenderer;
}
I understand that this helps using all the implementations of these classes without newing them up and also you don't have to decide WHICH implementaion to get, your IOC decides it for you, right?
but when I code like this, I do not even touch any IOC congiguration files. And again I am usin git for 2 days only but from all the tutorials that I have read, I was expecting my self to configure something which says "Resolve IParent to Child" class. But it works without me doing anything like it. Is it because there is only one implementaion of these interfaces? and If I do have more than one implementations then and then only I will have to configure resolved explicitly?
The code sample you have is a case of Constructor Injection.
In a traditional code, you would have a parameterless constructor, and in it you would "new-up" your objects like this:
IEmailService emailService = new EmailService();
So your code is explictly controlling which implementation gets assigned to the interface variable.
In IoC using constructor injection, control is inverted, meaning the container is "driving the bus" and is creating your TemplateEmailService object. When it is about to create it, the container looks at your constructor parameters (IEmailService , ITemplateRenderer , etc.) and feeds those objects to your class for use.
The IoC container can be configured so that interface A gets fulfilled by implementation B (or C) explicitly. Each one has a way to do it. Or it could do it by convention (IFoo fulfilled by Foo), or even attributes in classes, whatever.
So to answer your question-- you can explicitly define which implementations get used to fulfill certain interfaces. Got to read the IoC container docs for how to.
One more thing - "when you code like this", you technically don't have to be using an IoC container. In fact, your class should not have a direct reference to the container - it will maximize the reusability, and also allow easy testing. So you would wire-up interfaces to implementation classes elsewhere.

Resources