AutoMapper - Map destination object's property that does not exist in source object - asp.net-core

I'm casting class Process to ProcessDTO. The ProcessDTO object have a property named ProcessSteps that does not exist in Process. I want the ProcessSteps-property to be casted to ProcessStepsDto. I'm using a global configuration for AutoMapper.
I have tried using
CreateMap<Process, ProcessDto>()
.ForMember(dest=>dest.Steps, opt => opt.MapFrom(s => Mapper.Map<ProcessStepDto>(s)));
But this is wrong..
public class Process
{
}
public class ProcessDto
{
//This property does not exists in source object and get's created on get. I want this to be cast to "ProcessStepDto[]"
public ProcessStep[] Steps
{
get
{
ProcessStepRepository repository = new ProcessStepRepository();
return repository.Select(x => x.ProcessId == this.Id && x.Active).OrderBy(x=>x.Position).ToArray();
}
}
}
public class ProcessStep
{
...
}
public class ProcessStepDto
{
...
}
UPDATE
After i use AutoMapper to mapp my object Process to ProcessDto i also want the property of Stepsto be mapped to ProcessStepsDto. Currently it stays as ProcessStep.

If you want to return ProcessDto with ProcessStepDto[], the ProcessDto should define the property with type ProcessStepDto[] instead of ProcessStep[].
public class ProcessDto
{
public ProcessStepDto[] Steps
{
get
{
ProcessStepRepository repository = new ProcessStepRepository();
return repository.Select(x => x.ProcessId == this.Id && x.Active).Select(s => new ProcessStepDto { PropertyInProcessStepDto = s.PropertyInProcessStep }).OrderBy(x=>x.Position).ToArray();
}
}
}

Related

Polymorphism on a REST service

I am trying to clean and refactor my service code which currently looks like this-
public void generateBalance(Receipt receipt) {
if (receipt.getType().equals(X) && receipt.getRegion.equals(EMEA)) {
// do something to the receipt that's passed
} else if (receiptType.equals(Y)) {
// do something to the receipt
} else if (receipt.getRegion.equals(APAC) {
// call an external API and update the receipt
}....
...
// finally
dataStore.save(receipt);
Basically there's a bunch of conditionals that are in this main service which look for certain fields in the object that is being passed. Either it's the type or the region.
I was looking to use this design pattern- https://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html
However, I am not sure how this would work for a service class. Currently my REST handler calls this particular service. Also how can I do polymorphism for both the "receiptType" and "region"?
Is there a way I can just do all the updates to the receipt once in different services, then finally save the receipt at one location? (maybe a base class?) I am really confused on how to start. TIA!
If your classes should have the same behaviour, then it becomes pretty simple to use polymorpism. The pattern is called as Strategy. Let me show an example.
At first we need to use enum. If you do not have enum, then you can create a method which will return enum value based on your conditions:
if (receipt.getType().equals(X) && receipt.getRegion.equals(EMEA)) // other
// code is omitted for the brevity
So enum will look like this:
public enum ReceiptType
{
Emea, Y, Apac
}
Then we need an abstract class which will describe behaviour for derived classes:
public abstract class ActionReceipt
{
public abstract string Do();
}
And our derived classes will look this:
public class ActionReceiptEmea : ActionReceipt
{
public override string Do()
{
return "I am Emea";
}
}
public class ActionReceiptY : ActionReceipt
{
public override string Do()
{
return "I am Y";
}
}
public class ActionReceiptApac : ActionReceipt
{
public override string Do()
{
return "I am Apac";
}
}
Moreover, we need a factory which will create derived classes based on enum. So we can use Factory pattern with a slight modification:
public class ActionReceiptFactory
{
private Dictionary<ReceiptType, ActionReceipt> _actionReceiptByType =
new Dictionary<ReceiptType, ActionReceipt>
{
{
ReceiptType.Apac, new ActionReceiptApac()
},
{
ReceiptType.Emea, new ActionReceiptEmea()
},
{
ReceiptType.Y, new ActionReceiptY()
}
};
public ActionReceipt GetInstanceByReceiptType(ReceiptType receiptType) =>
_actionReceiptByType[receiptType];
}
And then polymorpism in action will look like this:
void DoSomething(ReceiptType receiptType)
{
ActionReceiptFactory actionReceiptFactory = new ActionReceiptFactory();
ActionReceipt receipt =
actionReceiptFactory.GetInstanceByReceiptType(receiptType);
string someDoing = receipt.Do(); // Output: "I am Emea"
}
UPDATE:
You can create some helper method which will return enum value based on
your logic of region and receiptType:
public class ReceiptTypeHelper
{
public ReceiptType Get(ActionReceipt actionReceipt)
{
if (actionReceipt.GetType().Equals("Emea"))
return ReceiptType.Emea;
else if (actionReceipt.GetType().Equals("Y"))
return ReceiptType.Y;
return ReceiptType.Apac;
}
}
and you can call it like this:
void DoSomething()
{
ReceiptTypeHelper receiptTypeHelper = new ReceiptTypeHelper();
ReceiptType receiptType = receiptTypeHelper
.Get(new ActionReceiptEmea());
ActionReceiptFactory actionReceiptFactory = new
ActionReceiptFactory();
ActionReceipt receipt =
actionReceiptFactory.GetInstanceByReceiptType(receiptType);
string someDoing = receipt.Do(); // Output: "I am Emea"
}

Public access to objects propery on aurelia validation

I would do like to have public access the private property where objects are stored on the current ValidationController as when we issue addObject().
From this blog:
http://www.jujens.eu/posts/en/2017/Jan/24/aurelia-validation/
I am trying to validate not only a WELL KNOWN object but ALL objects registered in the ValidationController
Let me explain a little bit, I had an interface called
export interface IRuleValidator {
addRules(model:any): void;
}
and classes that implement such interface
export class AddressRuleValidator implements IRuleValidator {
addRules(address: Address) {
ValidationRules
.ensure((a: Address) => a.address)
.required()
.on(address);
}
}
export class EmailRuleValidator implements IRuleValidator {
addRules(email: Email) {
ValidationRules
.ensure((e: Email) => e.email)
.required()
.on(email);
}
}
export class PhoneRuleValidator implements IRuleValidator {
addRules(phone: Phone) {
ValidationRules
.ensure((p: Phone) => p.phone)
.required()
.on(phone);
}
}
#inject(AddressRuleValidator, PhoneRuleValidator, EmailRuleValidator)
export class PlayerRuleValidator implements IRuleValidator {
private readonly addressRuleValidator: IRuleValidator;
private readonly phoneRuleValidator: IRuleValidator;
private readonly emailRuleValidator: IRuleValidator;
constructor(addressRuleValidator: IRuleValidator, phoneRuleValidator: IRuleValidator, emailRuleValidator: IRuleValidator) {
this.addressRuleValidator = addressRuleValidator;
this.phoneRuleValidator = phoneRuleValidator;
this.emailRuleValidator = emailRuleValidator;
}
addRules(player: Player) {
ValidationRules
.ensure((p: Player) => p.firstName)
.required()
.on(player);
if (player.addresses && player.addresses.length > 0)
player.addresses.map(address => this.addressRuleValidator.addRules(address));
if (player.phones && player.phones.length > 0)
player.phones.map(phone => this.phoneRuleValidator.addRules(phone));
if (player.emails && player.emails.length > 0)
player.emails.map(email => this.emailRuleValidator.addRules(email));
}
}
#inject(PlayerRuleValidator)
export class ScoreRuleValidator implements IRuleValidator {
private readonly playerRuleValidator: IRuleValidator;
constructor(playerRuleValidator: IRuleValidator) {
this.playerRuleValidator = playerRuleValidator;
}
addRules(score: Score) {
ValidationRules
.ensure((s: Score) => s.factor)
.required()
.on(score);
if (score.player) { this.playerRuleValidator.addRules(score.player); }
}
}
Each class knows how to validate the object passed to it and delegates to other classes the validation of "child" objects.
i.e.: score has a player and a player has emails.
Score knows how to validate to itself and delegates to player his own validation and player do the same with emails, phones, buildin all "the chain" down.
Thus the entire process of building a "validation chain" starts calling addRules() on the root object of the graph.
Suppose that we have an score object: We resolve from "the container" a ruleValidator for Score and starts buildind the validation chain as follows.
#inject(ScoreRuleValidator)
export class ScoreList extends BaseViewModel {
public isOk: boolean;
public score: Score
................ code removed for brevity (validation controller code )
#inject(ScoreRuleValidator)
constructor(ruleValidator: IRuleValidator) {
................ code removed for brevity (validation score object creation)
ruleValidator.addRules(this.score) //this call will start all the validation chain registration
this.validationController.validateTrigger = validateTrigger.changeOrBlur;
this.validationController.subscribe(event => this.validateAll())
}
}
private validateAll() {
this.validator
.validateObject(this.model)
.then(results => this.isOk = results.every(result => result.valid));
//HERE GOES THE PROBLEM SINCE ONLY SCORE is known, and what about score.player, and score.player.addresss[], score.player.phones[], score.player.emails[] and so on in the graph
//I WILL NEED to traverse all the chain and since ValidationController has track of those object will be greet to have access to them
}
HERE GOES THE PROBLEM SINCE ONLY SCORE is known, and what about score.player, and score.player.addresss[], score.player.phones[], score.player.emails[] and so on in the graph?.
I WILL NEED to traverse all the chain and since ValidationController has track of those object will be great to have access to it.
Meanwile an option is refactor the interface a rewrite the validator classes as follows:
export interface IRuleValidator {
addRules(model:any, models:any[]): void;
}
and pass an empty array from the root of the chain collecting all those objects.. like so..
export class AddressRuleValidator implements IRuleValidator {
addRules(address: Address, models: any[]) {
ValidationRules
.ensure((a: Address) => a.type)
.required()
.on(address);
models.push(address);
}
and kick the process.. with an empty array []
const objects: any[] = [];
ruleValidator.addRules(this.score, [])
But since we alreay have this property private on the ValidationController, please make it public.. (I will take care of not touching it, just read it)
BR
(then... the final method for validateAll should be like this)
private async validateAll() {
for (let model of this.models) {
let results = await this.validator.validateObject(model);
if (results.some(result => !result.valid)) {
this.isOk = false;
return;
}
}
this.isOk = true;
}
A deep look to the callback is the answer.
validationController.subscribe(event => this.validateAll())
the event object passed to the callback is an array of ValidateResult[]
the ValidateResult type implements the following interface.
export declare class ValidateResult {
rule: any;
object: any;
propertyName: string | null;
valid: boolean;
message: string | null;
private static nextId;
/**
* A number that uniquely identifies the result instance.
*/
id: number;
/**
* #param rule The rule associated with the result. Validator implementation specific.
* #param object The object that was validated.
* #param propertyName The name of the property that was validated.
* #param error The error, if the result is a validation error.
*/
constructor(rule: any, object: any, propertyName: string | null, valid: boolean, message?: string | null);
toString(): string | null;
}
so the object/s validated is already there in the event object
we could simplyfy the code as follow to update a field to signal if the htlm for is ready.
this.validationController.subscribe(validateEvent => this.isFormValid = validateEvent.results.every(result => result.valid));

PHP Youshido GraphQL issue with nested fields

I am using version v1.4.2.18. The library can be found here: https://github.com/Youshido/GraphQL
I am trying to accomplish the following:
query {
articleSummary(id:1) {
title,
body,
article {
id
}
}
}
I have an ArticleSummaryField.php:
class ArticleSummaryField extends AbstractField
{
public function build(FieldConfig $config)
{
$config->addArgument('id', new NonNullType(new StringType()));
}
public function getType()
{
return new ArticleSummaryType();
}
public function resolve($value, array $args, ResolveInfo $info)
{
return [
'title' => 'test title',
'body' => 'test body',
'article' => $args['id']
];
}
}
Then the ArticleSummaryType.php:
class ArticleSummaryType extends AbstractObjectType
{
public function build($config)
{
$config
->addField('title', new StringType());
->addField('body', new StringType());
->addField('article', new ArticleField());
}
}
Then the ArticleField.php has the getType method return the ArticleType which has the id field.
However what i am getting is an error:
Fatal error: Uncaught Error: Call to undefined method ArticleField::getNullableType() in .../vendor/youshido/graphql/src/Execution/Processor.php on line 135
What seems to be happening is that when $targetField->getType() on line 135 in src/Execution/Processor.php is called its returning the ArticleField class, not the ArticleType class.
I would expect that to return the class as declared in the 'getType' method on the ArticleField class.
Am i going about this wrong for nesting fields? Or is there a bug in the library?
To accomplish this you only pass the Field class as the first argument.
class ArticleSummaryType extends AbstractObjectType
{
public function build($config)
{
$config
->addField('title', new StringType());
->addField('body', new StringType());
->addField(new ArticleField());
}
}
Then in the field class you can override getName to set the name for the field as needed or it will use the class name as the field name.

NHibernate Dynamic Component Default Value Issue

All of my entities (that are mapped to a database table) inherit from an entity class with a dynamic component on it called Attributes e.g.:
public abstract class Entity<T> {
public virtual T Id { get; set; }
private IDictionary _attributes;
public virtual IDictionary Attributes {
get { return _attributes ?? (_attributes = new Hashtable()); }
set { _attributes = value; }
}
}
The Attributes collection allows me to add extra fields to each entity without directly changing the entity itself. This allows me to make my application more modular.
For example say I have the following entity:
public class User : Entity<int> {
public virtual string Name { get; set; }
}
Now say I have a Forum module which needs a NumPosts property against the User. I would add the field against the Users table in the database. This field is non nullable and has a default value of 0. I then map the field using the dynamic component against the User entity.
However when I try inserting the user by saying:
session.Save(new User() { Name = "Test" });
It throws an error as it's expecting me to set a value for NumPosts and the generated SQL would be something like:
INSERT INTO Users (Name, NumPosts) VALUES ('Test', NULL)
However NumPosts does not allow nulls and hence the error. Ideally I'd like it to say the following if the Attributes collection does not contain an entry for NumPosts:
INSERT INTO Users (Name) VALUES ('Test')
An alternative is to say the following which would work fine:
session.Save(new User() { Name = "Test", Attributes = new Hashtable() { { "NumPosts", 0 } } });
The problem I have is that I don't want the modules to have a dependency on each other and I can't really say this.
For reference here's a bare bones version of session factory method which maps the NumPosts field:
return Fluently.Configure()
...
.ExposeConfiguration(c => {
// Get the persistent class
var persistentClass = c.GetClassMapping("User");
// Create the attributes component
var component = new Component(persistentClass);
// Create a simple value
var simpleValue = new SimpleValue(persistentClass.Table);
// Set the type name
simpleValue.TypeName = "Int32";
// Create a new db column specification
var column = new Column("NumPosts");
column.Value = simpleValue;
column.Length = 10;
column.IsNullable = false;
column.DefaultValue = "0";
// Add the column to the value
simpleValue.AddColumn(column);
// Ad the value to the component
component.AddProperty(new Property() { Name = column.Name, Value = simpleValue });
// Add the component property
persistentClass.AddProperty(new Property() { Name = "Attributes", Value = component });
})
.BuildConfiguration();
I'd appreciate if someone could let me know if this is possible. Thanks
You know how to make it working as described above:
... An alternative is to say the following which would work fine:
session.Save(new User()
{
Name = "Test", Attributes = new Hashtable() { { "NumPosts", 0 } }
});
... The problem I have is that I don't want the modules to have a dependency on each other and I can't really say this...
In case, that the biggest issue is the explicit Attributes initialization ("...I don't want the modules to have a dependency...") we can use:
12.2. Event system
So, with Listener like this:
[Serializable]
public class MyPersistListener : NHibernate.Event.ISaveOrUpdateEventListener
{
public void OnSaveOrUpdate(SaveOrUpdateEvent #event)
{
var entity = #event.Entity as Entity<int>; // some interface IHaveAttributes
if (entity == null) // would be more appropriate
{
return;
}
var numPosts = entity.Attributes["NumPosts"] as int?;
if (numPosts.HasValue)
{
return;
}
entity.Attributes["NumPosts"] = 0;
}
}
Based on this doc snippet:
Configuration cfg = new Configuration();
ILoadEventListener[] stack = new ILoadEventListener[] { new MyLoadListener(), new DefaultLoadEventListener() };
cfg.EventListeners.LoadEventListeners = stack;
This should be the init in our case:
.ExposeConfiguration(c => {
var stack = new ISaveOrUpdateEventListener [] { new MyPersistListener() };
c.EventListeners.SaveEventListeners= stack;

How do I bind generic types with inheritance using Ninject Conventions extensions

How can I bind InitializerForXXX (non-generic implementation) to IInitializer<XXX> (generic interface) using Ninject Conventions so that requests for an IInitializer<T> resolve a non-generic implementation whose name starts with InitializerFor and end with typeof(T).Name like:
initializerFactory.CreateFor<Blue>(); //resolves InitializerOfBlue
initializerFactory.CreateFor<ShadeOfBlue>(); //resolves InitializerOfShadeOfBlue
where no non-abstract class directly implement IInitializer<T>, and some implementations inherit from other implementations:
InitializerForShadeOfBlue inherits from InitializerForBlue
InitializerForBlue inherits from abstract Initializer<Blue>
abstract Initializer<T> directly implements IInitializer<T>
I'm hoping I can use a .EndsWith(typeof(T).Name) for a given IInitializer<T> convention I can use, because there are literally hundreds of initializers in the ShadeOfxxx vein. If I have to map all of them, I'm better off finding a way to resolve with reflection at runtime.
Given the following:
UPDATE: bindings with custom binding generator (see my answer below for implementation)
void Bootstrap(IBindingRoot kernel)
{
kernel.Bind<IInitializerFactory>()
.To<InitializerFactory>()
.InSingletonScope();
kernel.Bind(scanner =>
scanner.FromThisAssembly().SelectAllClasses()
.WhichAreNotGeneric()
.InheritedFrom(typeof(IComplexContent))
.BindAllInterfaces());
kernel.Bind(scanner =>
scanner.FromThisAssembly().SelectAllClasses()
.WhichAreNotGeneric()
.InheritedFrom(typeof(IInitializer<>))
.BindWith<FirstTypeParameterNameMatchesEndOfBoundClassNameGenerator>());
}
main method
void Main(IEnumerable<string> values)
{
// setup bindings
var kernel = new StandardKernel();
Bootstrap(kernel);
IInitializerFactory initializerFactory =
kernel.Get<IInitializerFactory>();
IInitializer<ShadeOfBlueComplexContent> initializer =
initializerFactory.CreateFor<ShadeOfBlueComplexContent>();
initializer.Initialize(values);
}
initializer factory
interface IInitializerFactory
{
IInitializer<T> CreateFor<T>() where T : class, IComplexContent, new();
}
class InitializerFactory : IInitializerFactory
{
public IInitializer<T> CreateFor<T>() where T : class, IComplexContent, new()
{
return MagicallyGetInitializer<T>();
}
//behind the curtain, whirring noises are heard as 't' is resolved...
private static IInitializer<T> MagicallyGetInitializer<T>()
where T : class, IComplexContent, new()
{
IInitializer<T> i = null;
return i;
}
}
initializers
interface IInitializer<out T> where T : IComplexContent
{
T Initialize(IEnumerable<string> values);
}
abstract class Initializer<T> : IInitializer<T> where T : IComplexContent
{
public abstract T Initialize(IEnumerable<string> values);
}
class InitializerOfBlue : Initializer<Blue>
{
private readonly Blue _content;
public InitializerOfBlue(Blue content) {_content = content;}
public override Blue Initialize(IEnumerable<string> values)
{
_content.BlueSpecificProperty = values.ElementAt(0);
//... populate other blue-specific properties like this
return _content;
}
}
class InitializerOfShadeOfBlue : InitializerOfBlue
{
public InitializerOfShadeOfBlue(ShadeOfBlue content) : base(content){}
}
content models
interface IComplexContent
{
string OneBasicProperty { get; set; }
// other properties are specific to implementation
string UniqueOperation();
}
abstract class BaseComplexContent : IComplexContent
{
public string OneBasicProperty { get; set; }
public abstract string UniqueOperation();
}
class Blue : BaseComplexContent
{
// initializer sets this
public string PropertyForAllKindsOfBlue { get; set; }
// initializer doesn't interact with this
public override string UniqueOperation() {return "I'm plain.";}
}
class ShadeOfBlue : Blue
{
// initializer doesn't interact with this
public override string UniqueOperation() {return "I'm fabulous!";}
}
You are over specifying the class selection
kernel.Bind(scanner =>
scanner.FromThisAssembly().SelectAllClasses()
.WhichAreNotGeneric()
.InheritedFrom(typeof (IInitializer<>))
This is already enough. What you need to do though is to add a custom Binding Generator. That selects IInitializer<Blue> for InitializerForBlue and IInitializer<ShadeOfBlue> for InitializerForShadeOfBlue
https://github.com/ninject/ninject.extensions.conventions/wiki/Projecting-Services-to-Bind
BEGIN SOLUTION CANDIDATE - custom binding generator:
custom binding generator
Thanks for the advice, #RemoGloor and #RubenBartelink. I'm stumped though - the problem is that I wind up binding the IInitializer<Blue> to InitializerOfShadeOfBlue. I need to be able to somehow change the generic type argument from Blue to ShadeOfBlue in the IInitializer<Blue> binding candidate, since IInitializer<ShadeOfBlue> is what will be requested from the factory method at runtime.
Is there a way to modify the generic type argument list of the binding candidate? Or am I barking up the wrong implementation? Any edit suggestions to my OP or this answer are appreciated.
/// <summary>Creates bindings on open generic types where bound implementations'
/// names end with the name of the generic type argument</summary>
public class FirstTypeParameterNameMatchesEndOfBoundClassNameGenerator : IBindingGenerator
{
public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
{
if (type == null) throw new ArgumentNullException("type");
if (bindingRoot == null) throw new ArgumentNullException("bindingRoot");
// only consider concrete, non-abstract classes
if (type.IsInterface || type.IsAbstract) yield break;
var bindingType = GetBindingType(type);
if (bindingType != null)
yield return bindingRoot.Bind(bindingType).To(type);
// ARGH! bindingType == IInitializer`1[[Blue]] but I want
// IInitializer`1[[ShadeOfBlue]] for type == ShadeOfBlue
}
private static Type GetBindingType(Type type)
{
Type goodMatch = null;
foreach (var candidate in type.GetInterfaces())
{
// skip non-generic interfaces
if (!candidate.IsGenericType) continue;
// assumption: using argument in first position
var firstArg = candidate.GetGenericArguments().First();
if (!type.Name.EndsWith(firstArg.Name)) continue;
// IInitializer<XXX> matches InitializerOfXXX
goodMatch = candidate;
break;
}
if (goodMatch == null)
{
// if no match on interfaces, walk through the ancestor types
foreach (var candidate in type.GetAllAncestors())
{
goodMatch = GetBindingType(candidate);
if (goodMatch != null) break;
}
}
return goodMatch;
}
Type Extension helper
public static class TypeExtensions
{
// returns all ancestor types starting with the parent
public static IEnumerable<Type> GetAllAncestors(this Type type)
{
for (var current = type.BaseType; current != null; current = current.BaseType)
yield return current;
}
}
END SOLUTION CANDIDATE - custom binding generator