In Vaughn Vernon Implementing Domain-driven Design book and code, he uses a mix of Identity and ValueObject for identifiers.
public interface IIdentity
{
string Id { get; }
}
public abstract class Identity : IEquatable<Identity>, IIdentity
{
protected Identity() => this.Id = Guid.NewGuid().ToString();
protected Identity(string id) => this.Id = id;
// Currently for Entity Framework, set must be protected, not private. will be fixed in EF 6.
public string Id { get; protected set; }
public bool Equals(Identity id)
{
if (object.ReferenceEquals(this, id)) return true;
if (object.ReferenceEquals(null, id)) return false;
return this.Id.Equals(id.Id);
}
public override bool Equals(object anotherObject) => Equals(anotherObject as Identity);
public override int GetHashCode() => (this.GetType().GetHashCode() * 907) + this.Id.GetHashCode();
public override string ToString() => this.GetType().Name + " [Id=" + Id + "]";
}
And value objects:
public abstract class ValueObject
{
// Returns all components of a value objects which constitute its identity.
protected abstract IEnumerable<object> GetEqualityComponents();
public override bool Equals(object obj)
{
if (object.ReferenceEquals(this, obj)) return true;
if (object.ReferenceEquals(null, obj)) return false;
if (this.GetType() != obj.GetType()) return false;
var vo = obj as ValueObject;
return GetEqualityComponents().SequenceEqual(vo.GetEqualityComponents());
}
public override int GetHashCode() => HashCodeHelper.CombineHashCodes(GetEqualityComponents());
}
I see in some cases a ValueObject is used as an identity:
public class TaskId : ValueObject
{
public TaskId()
: this(Guid.NewGuid().ToString().ToUpper().Substring(0, 8))
{
}
public TaskId(string id)
{
AssertionConcern.AssertArgumentNotEmpty(id, "The id must be provided.");
AssertionConcern.AssertArgumentLength(id, 8, "The id must be 8 characters or less.");
this.Id = id;
}
public string Id { get; private set; }
protected override IEnumerable<object> GetEqualityComponents()
{
yield return this.Id;
}
}
And other cases they are a pure Identity:
public class ForumId : SaaSOvation.Common.Domain.Model.Identity
{
public ForumId(string id) : base(id) { }
}
To me, all values should be a value object, including identities, so I don't understand the differentiation here in having an explicit Identity type.
With his demo code, how/why is he choosing the above approaches to modeling identity and is there any advantage/disadvantage over the other?
Both implementations are comparing properties for equality, so both follow the concept of a value object. The Identity class is dedicated to be a reusable value object for custom identity types which still share the same requirements (using an arbitrary string, usually created from a GUID/UUID). Still a value object,but if no other properties than a string id are needed this one can be used in such cases while still strongly typing different types of identities with separate derived classes (like ForumId).
The ValueObject class on the other hand is dealing with arbitrary properties that need to be compared in the respective derived classes.
I think the intention to derive TaskId from ValueObject rather than from Identity becomes clearer if you look at the constructor. In this case a specific business rule - the id must be eight characters or less - needs to be fulfilled upon construction which would not make sense for the definition of the general identity implementation.
Related
I often have Models and Dtos like this:
// DTO class
public class OrderDto
{
public int Id { get; set; }
public DateTime Date { get set; }
public int ProductId { get; set; }
// ...
}
// Model class
public class Order : BaseObject
{
public DateTime Date { get set; }
public Product Product { get; set; }
// ...
}
// Model class
public class Product : BaseObject
{
// ...
}
In order to map my OrderDto to the Order class I have to configure AutoMapper for this particular "association" like so:
CreateMap<OrderDto, Order>()
.ForMember(m => m.Product, d => d.ResolveUsing((d, m) =>
{
return m.Session.GetObjectByKey<Product>(dto.ProductId);
}))
This is quite cumbersome to do this for each case like this. Therefore I was looking into generalizing this behaviour by using a custom TypeConverter class:
public class IntBaseObjectTypeConverter : ITypeConverter<int, BaseObject>
{
private UnitOfWork uow;
// ...
public BaseObjectConvert(int source, BaseObject destination, ResolutionContext context)
{
return uow.Session.GetObjectByKey(typeof(destination), source);
}
}
However, this will fail of course if the destination is null. Unfortunately the ResolutionContext does not give me any clue about the specific type of the destination property.
Now my question is, if there is another way to achieve with AutoMapper what I would like to do?
Please note that I am not using Entity Framework which of course would solve this issue on the model level with foreign key and navigational properties. I use XPO from DevExpress which does not allow foreign key and navigational properties like in Entity Framework.
I'm having trouble implementing Automapper conversion in a situation where the source is a class which should be mapped to one of two derived classes based on a value on the source.
Here's a simplification of my classes:
public class FooContainerDTO
{
public FooDTO Foo { get; set; }
}
public class FooDTO
{
public string Type { get; set; }
//some properties..
}
public class FooContainer
{
public FooBase Foo { get; set; }
}
public abastract class FooBase
{
//some properties..
}
public class FooDerived1 : FooBase
{
//some properties
}
public class FooDerived2 : FooBase
{
//some properties
}
I'm using non-static Automapper so I create a MapperConfiguration from several Profiles at boot and inject the IMapper instance into my DI-container.
I want Automapper to map FooDTO to FooDerived1 when its Type property is "der1" and to FooDerived2 when it is "der2".
I've seen examples on this using the static api, something like this:
Mapper.CreateMap<FooContainerDTO, FooContainer>();
//ForMember configurations etc.
Mapper.CreateMap<FooDTO, FooDerived1>();
//ForMember configurations etc.
Mapper.CreateMap<FooDTO, FooDerived2>();
//ForMember configurations etc.
Mapper.CreateMap<FooDTO, FooBase>()
.ConvertUsing(dto => dto.Type == "der1"
? (FooBase) Mapper.Map<FooDerived1>(dto)
: Mapper.Map<FooDerived2>(dto));
This would map the Foo property of FooContainer to the correct derived type of FooBase.
But how can I do this without the static API?
The IMapper instance is not yet created at the point of configuring the profile.
Is there a way to leverage the overload of ConvertUsing() which takes a Func< ResolutionContext,object >? Can the resolution context give me whatever IMapper is currently being used? I've been looking, but can't find anything usable.
One way to get access to the mapping engine is via your own TypeConverter
abstract class MyTypeConverter<TSource,TDestination> : ITypeConverter<TSource, TDestination>
{
protected ResolutionContext context;
public TDestination Convert(ResolutionContext context)
{
this.context = context;
return Convert((TSource)context.SourceValue);
}
public abstract TDestination Convert(TSource source);
}
You then create an actual implementation like:
class MyTypeMapper : MyTypeConverter<EnumType,EnumTypeView>
{
public override EnumTypeView Convert(EnumType source)
{
return context.Engine.Mapper.Map<EnumTypeID, EnumTypeView>(source.EnumBaseType);
}
}
Except instead of unwrapping an enum structure, you'd check the type and call Map with different types.
I have a few properties that I don't have a direct mapping in the database for, so I'm using the convention of having another variable that is mapped to the database, and a public variable that will be used to do all of my actual work. The common one is [mapping a boolean property to a char column][1], but I also have a StatusID property whose C# enum is different based on the derived type.
My public property has the [NotMapped] attribute on it, and my internal property has the [Column] attribute. I think there's something that because the public property isn't mapped, it's keeping the other property from being mapped as well.
In my project, I start with an abstract base Message class:
[Table("tblMessage")]
public abstract class Message {
[Column("msgIsSample")]
[Required]
internal string dbIsSample { get; set; }
[Column("msgStatusID")]
internal int? dbStatusId { get; set; }
[NotMapped]
public bool IsSample {
get {
return dbIsSample.ToUpper() == "Y";
}
set {
dbIsSample = value ? "Y" : "N";
}
}
public Message() {
this.IsSample = false;
this.dbStatusId = null;
}
}
Right now I only have a single class implementing the base class, Request:
public class Request : Message {
[NotMapped]
public int Status {
get {
return this.dbStatusId.HasValue ? this.dbStatusId.Value : 1;
}
set {
this.dbStatusId = value;
}
}
public Request()
: base() {
this.Status = 1;
}
}
Here is my context:
public class MyContext : DbContext {
public DbSet<Message> Messages { get; set; }
static MyContext() {
Database.SetInitializer<MyContext>(null);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Entity<Message>()
.Map<Request>(m => m.Requires("msgTypeID").HasValue(1));
}
}
Is this something that anyone else has run across? I haven't been able to find anything about why this isn't working, even though this looks like the accepted convention until the EF team adds additional custom mapping. Someone else has to have run across this issue.
When I try to execute this code, I get a DbUpdateException saying that it can't insert a NULL into column "msgIsSample" due to my having set that in the table creation script. This doesn't make any sense because the msgIsSample is defaulted to have a "N".
Instead of making it internal, make it protected internal.
At runtime, EF will subclass your entity dynamically. These extended classes are called dynamic proxies.
EF cannot set your property because it does not have access. To give EF access to your property, it must have either public or protected access. You can still have internal properties, but give subclasses access by adding the protected modifier.
[Table("tblMessage")]
public abstract class Message {
[Column("msgIsSample")]
[Required]
public string dbIsSample { get; protected internal set; }
[Column("msgStatusID")]
public int? dbStatusId { get; protected internal set; }
Here is a sample of what I am trying to accomplish:
public class BaseClass<T>
{
public static T GetByID(int ID)
{
// Need database name here that is determined at design time in the derived class.
var databaseName = "";
// do some stuff involving database name that gets me object by ID here.
return default(T);
}
}
public class DerivedClass : BaseClass<DerivedClass>
{
private string DatabaseName { get; set; }
}
Basically, how would I access the derived "DatabaseName" in the base class static GetByID method?
EDIT: After I posted this, I tried one more thing. I played with attributes earlier, and failed, but I think my brain was mushy. Just tried again and ran a test, and it is working. Here is the updated sample.
public class BaseClass<T>
{
public static T GetByID(int ID)
{
// Need database name here that is determined at design time in the derived class.
var databaseName = ((DatabaseAttribute)typeof(T).GetCustomAttributes(typeof(DatabaseAttribute), true).First()).DatabaseName;
// do some stuff involving database name that gets me object by ID here.
return default(T);
}
}
[Database("MyDatabase")]
public class DerivedClass : BaseClass<DerivedClass>
{
}
public class DatabaseAttribute : Attribute
{
public DatabaseAttribute(string databaseName)
{
DatabaseName = databaseName;
}
public string DatabaseName { get; set; }
}
Base class to derived class is a one-way inheritance: The base class has no knowledge of the existance of a derived class, and so it can't access it.
In addition to that you will have a hard time accessing a non-static property from a static method.
I know you've already answered your own question, but some improvements....
Add a where clause to guarantee inheritance, it means any static methods can make use of inherited methods. You might also want to add the new() clause if you wish to be able to create instances of the inherited class.
public class BaseClass<T> : where T : BaseClass<T>
{
static readonly string databaseName;
static BaseClass() {
// Setup database name once per type of T by putting the initialization in
// the static constructor
databaseName = typeof(T).GetCustomAttributes(typeof(DatabaseAttribute),true)
.OfType<DatabaseAttribute>()
.Select(x => x.Name)
.FirstOrDefault();
}
public static T GetByID(int ID)
{
// Database name will be in the static field databaseName, which is unique
// to each type of T
// do some stuff involving database name that gets me object by ID here.
return default(T);
}
}
[Database("MyDatabase")]
public class DerivedClass : BaseClass<DerivedClass>
{
}
public class DatabaseAttribute : Attribute
{
public DatabaseAttribute(string databaseName)
{
DatabaseName = databaseName;
}
public string DatabaseName { get; set; }
}
I need to register all concrete type of a specific interface with structuremap
the problem I have is that these concrete types just have a ctor with primitive parameters, and these parameters would be dynamiclly differen
public interface IPropertyType
{
string PropertyName { get; set; }
string DisplayName { get; set; }
}
public abstract class PropertyTypeBase : IPropertyType
{
public PropertyTypeBase(string propertyName, string displayName)
{
PropertyName = propertyName;
DisplayName = displayName;
}
}
public class StringType : PropertyTypeBase
{
public StringType(string propertyName, string displayName)
: base(propertyName,displayName)
{
//do sth
}
}
all concrete types like StringType have these 2 parameter that are different from each other and they would declare during run time, how can I register all of these types
Given the fact that both properties are public get and set I would remove them from your constructor. I see no reason at all why you would want to have these injected as they're not dependencies and can be reset afterwards anyway.