I am facing a class resolution issue while trying to make my architecture flexible. To make it simple, consider the following example:
I have four tiers: UI, BL, Common and DAL
I have a base class in my BL layer as defined below:
public class User
{
private UserDTO _d;
public User()
{
_d = new UserDTO();
}
public User(UserDTO d)
{
_d = new UserDTO(d);
}
public UserDTO D
{
get { return _d; }
set { _d = value; }
}
//static method (I cannot make it non-static due to some reasons)
public static User GetUser()
{
User user = new User(Provider.DAL.GetUser());
return user;
}
}
The DTO is defined as:
public class UserDTO
{
public int ID;
public UserDTO()
{
}
public UserDTO(UserDTO source)
{
ID = source.ID;
}
}
My DAL is defined as (it returns a DTO not a business object):
public static UserDTO GetUser()
{
UserDTO dto = new UserDTO();
dto.ID = 99;
return dto;
}
Now, I want to "extend" my code so that I can have one more field in my User table: Name. So I create a derived DTO class as:
public class MyUserDTO : UserDTO
{
public string Name;
public MyUserDTO()
{
}
public MyUserDTO(MyUserDTO source)
{
Name = source.Name; //new field
base.ID = source.ID;
}
}
Then, I create a derived User class as:
public class MyUser : User
{
public MyUser()
{
this.D = new MyUserDTO();
}
}
And I create my own custom DAL provider with this method:
public static UserDTO GetUser()
{
UserDTO dto = new MyUserDTO();
dto.ID = 99;
((MyUserDTO)dto).Name = "New Provider Name";
return dto;
}
Now when I access this MyUserDTO object in my BL, it loses resolution:
User.GetUser(DAL.Provider.GetUser())
and in the UI, I dont get the properties in the MyUserDTO.
Is there a method which can help me get those properties in the UI layer, even after I call the static User.GetUser() method (which will in turn call my custom provider returning a MyUserDTO object)?
Thanks,
You don't inherit from a class to add in new data, only inherit if your new class is going to extend the behaviour of your old class.
Give your UserDTO a Name-Value collection to hold its data and populate that. Then you won't have an issue.
You're not getting the derived behaviour because the static method in the user class can't be overriden by the MyUser class.
You should remove the static method (I know you've indicated you can't), but really you should.
Try to extract the creation of your users in another object (factory, repository,...)
As others have mentioned, the problem is with the static method.
I would also suggest using generics or dependency injection to clean up your parallel object hierarchy. You don't want that duplication.
Instead of having a set of almost-identical 'User' and 'MyUser' classes, that have the same hierarchy, just do something like User and plug in the UserDTO type that you want.
If you refactor and remove the object hierarchy duplication, it may make it easier to see a good solution to get around the problem with the static GetUser().
From what I can see it looks like User.GetUser() will return a User object, not a MyUserDTO object, which is why you don't get those extra fields. The DAL layer needs to abide by the contract it was written against. There are a handful of ways you could go about solving this, although some are more "right" than others.
You could cast the object you get out of User.GetUser to the appropriate object which would then give you access to the casted object's fields (assuming the object can be cast to that type). I don't really like this solution from a design perspective, but it would work:
MyDTOUser myDtoUser = User.GetUser() as MyDTOUser;
Other people have posted some other examples of ways around this so I won't repeat those here.
Related
I am curently working on a small project (C#) where I have data to analyse.
To do so, I pass the data into the constructor of a class.
The class makes a first analysis on the data, and a certain value is determined using the data. Using this value I can say that this data is of Type B, C, D, ... and the analysis would continue in another class corresponding to the data type.
This would be it's class diagram representation :
So the "Data" Class should abstract but not really ? ¯\_(ツ)_/¯
I did some reasearch about the factory design pattern, but I think this is not really what I am trying to achieve. Is there maybe an other design pattern that does what I want to do?
Thank you for helping.
If I understand you correctly, you want the base class to determine which child class to create based on the data passed into the constructor. If so, you can't do it that way - a class cannot change itself to be a different/derived type when being constructed.
I assume that all the data types have some common properties and so you decided to put those common properties in a base class. I also assume you don't want each data type child class to have redundant code setting those common properties in the base class. You accomplish that by having the child class call a method in the base class, passing the data. You can do this in the constructors if you wish. For example:
class BaseData
{
BaseData(Dictionary<string,string> data)
{
this.CommonProp1 = data["CommonProp1"];
this.CommonProp2 = data["CommonProp2"];
}
public string CommonProp1 { get; set; }
public string CommonProp2 { get; set; }
}
class DataTypeA : BaseData
{
DataTypeA(Dictionary<string,string> data)
: base(data) // <-- magic here
{
this.TypeA_Prop1 = data["TypeA_Prop1"];
this.TypeA_Prop2 = data["TypeA_Prop2"];
}
public string TypeA_Prop1 { get; set; }
public string TypeA_Prop2 { get; set; }
}
I believe the factory pattern actually is what you want since you want to create an instance of a class in which the type is determined at run time. This is where you encapsulate the code that determines which type of child class to create. Something like:
class DataFactory
{
public static BaseData BuildDataClass(byte[] serializedData)
{
Dictionary<string,string> data = ParseData(serializedData);
switch (data["DataType"])
{
case "TypeA":
return new DataTypeA(data);
default:
return null;
}
}
private static Dictionary<string,string> ParseData(byte[] serializedData)
{
var data = new Dictionary<string, string>();
// bla bla
return data;
}
}
I have an entity named "Task". For this entity I can create multiply entities, called "Comment". I want also to have a method named "CreateComment". According to the Domain Driven Design, the entity "Comment" can not exist without creating an instance of "Task" class. And my question is: where this method should be placed: in the Task class or in the Comment class? should it be like Comment.CreateComment or Task.CreateComment. If I put this method to the Task class, would it be the Single responsibility principle violation?
I believe that the method should be be on the Task entity. But that being said the method should not be Create but rather Add as I do not believe it is a responsibility of the Task object to create a comment. Instead I'd use something like this, which is an overkill but mostly because I like a progress fluent interface and the object builder pattern :)
Task class, pretty self explanatory
public class Task
{
private readonly IList<Comment> Comments = new List<Comment>();
public void AddComment(ICommentBuilderFinalization commentBuilder)
{
Comments.Add(commentBuilder.MakeComment());
}
}
Comment class, pretty self explanatory once again
public class Comment
{
public string Text { get; set; }
public string PostedBy { get; set; }
public DateTime PostedAt { get; set; }
}
The object builder and progressive fluent interfaces
// First progressive interface
public interface ICommentBuilder
{
ICommentBuilderPostBy PostWasMadeNow();
ICommentBuilderPostBy PostWasMadeSpecificallyAt(DateTime postedAt);
}
// Second progressive interface
public interface ICommentBuilderPostBy
{
ICommentBuilderPostMessage By(string postedBy);
}
// Third progressive interfacve
public interface ICommentBuilderPostMessage
{
ICommentBuilderFinalization About(string message);
}
// Final
public interface ICommentBuilderFinalization
{
Comment MakeComment();
}
// implementation of the various interfaces
public class CommentBuilder : ICommentBuilder, ICommentBuilderPostBy, ICommentBuilderPostMessage, ICommentBuilderFinalization
{
private Comment InnerComment = new Comment();
public Comment MakeComment()
{
return InnerComment;
}
public ICommentBuilderFinalization About(string message)
{
InnerComment.Text = message;
return this;
}
public ICommentBuilderPostMessage By(string postedBy)
{
InnerComment.PostedBy = postedBy;
return this;
}
public ICommentBuilderPostBy PostWasMadeNow()
{
InnerComment.PostedAt = DateTime.Now;
return this;
}
public ICommentBuilderPostBy PostWasMadeSpecificallyAt(DateTime postedAt)
{
InnerComment.PostedAt = postedAt;
return this;
}
}
Putting it all together
var task = new Task();
var commentBuilder = new CommentBuilder().PostWasMadeNow().By("Some User").About("Some Comment");
task.AddComment(commentBuilder);
Ok, so as I mentioned earlier this example is way over engineered for most situations. But it should give you an idea as to what you can do to stay true to the Single Responsibility Principle.
According to GRASP, principles
class B should be responsible for creating instances of class A if one, or preferably more, of the following apply:
Instances of B contain or compositely aggregate instances of A
Instances of B record instances of A
Instances of B closely use instances of A
Instances of B have the initializing information for instances of A and pass it on creation.
From your description it sounds like at least 3 of those points are pertinent. Therefore I would say that Task is responsible for creating Comment.
I have a WCF service which exposes its interface with DTOs. I have an entity class MyClass which has two properties SimpleProperty1 and SimpleProperty2. There is a calculated property in this class named CalculatedProperty1 which uses the above two properties in calculating its value. I have a MyClassDTO dto class which has only the two simple properties.
In the UI, where a MyClassDTO object is being modified, I want the user to see the value of CalculatedProperty on the fly. However, as according to my understanding DTOs should not have any logic embedded in them. And it seems a bit of a waste to implement a function in the web service to get the calculated value of the property in such a simple scenario. How should I go about getting this done? What are the standard approaches of doing this? I see that the generated classes from the WCF service are defined as partial classes. Is it there to handle this sort of scenario?
you can use extension method to show the calculated property
public class MyClassDTO
{
public string P1 { get; set; }
public string P2 { get; set; }
}
public static class MyClassDtoExtension
{
public static string ToCalculatedProperty(this MyClassDTO obj)
{
return obj.P1 + obj.P2;
}
}
// usage
var d = new MyClassDTO(){P1 = "1",P2 = "2"};
d.ToCalculatedProperty();
I'm wrapping my ORM entities into bussines objects.
public class ProjectMember
{
private readonly TfProjectMembersEntity _projectMembersEntity;
public ProjectMember(TfProjectMembersEntity projectMembersEntity)
{
_projectMembersEntity = projectMembersEntity;
}
#region Props
public string Email
{
get { return _projectMembersEntity.Email; }
set { _projectMembersEntity.Email = value; }
}
public DateTime Created
{
get { return _projectMembersEntity.Created; }
set { _projectMembersEntity.Created = value; }
}
}
This bussines objects are returned by the repository. The way out isn't complicated. The problem is how to access the wrapped entity when a wrapped object is passed to a repository for a save operation.
What would be a neat way, to get the wrapped object ?
Simply add a method or property?
You could create an Interface like so:
interface IWrappedEntity<T>
{
T GetWrappedEntity();
}
Now you could make your BOs implement that interface. You could even create a base class implementing that interface and derive your BOs from that base class.
EDIT:
Changed DTO to Entity to conform with your code.
How can i check/evaluate the exact type of T without an object for T. I know my question maybe confusing but consider this...
public abstract class Business
{
public abstract string GetBusinessName();
}
public class Casino : Business
{
public override string GetBusinessName()
{
return "Casino Corp";
}
}
public class DrugStore : Business
{
public override string GetBusinessName()
{
return "DrugStore business";
}
}
public class BusinessManager<T> where T : Business
{
private Casino _casino;
private DrugStore _drugStore;
public string ShowBusinessName()
{
string businessName;
if (T == Casino) // Error: How can I check the type?
{
_casino = new Casino();
businessName = _casino.GetBusinessName();
}
else if (T == DrugStore) // Error: How can I check the type?
{
_drugStore = new DrugStore();
businessName = _drugStore.GetBusinessName();
}
return businessName;
}
}
I just want to have something like this on the client.
protected void Page_Load(object sender, EventArgs e)
{
var businessManager = new BusinessManager<Casino>();
Response.Write(businessManager.ShowBusinessName());
businessManager = new BusinessManager<DrugStore>();
Response.Write(businessManager.ShowBusinessName());
}
Notice that I actually didnt create the actual object for Casino and Drugstore when I call the BusinessManager, I just pass it as generic type constraint of the class. I just need to know exactly what Type i am passing BusinessManager to know what exactly the Type to instantiate. Thanks...
PS: I don't want to create separate specific BusinessManager for Casino and Drugstore..
You can also comment about the design.. thanks..
ADDITIONAL: and what if class Casino and DrugStore is an ABSTRACT CLASS =)
You can write
if(typeof(T) == typeof(Casino))
but really this type of logic is a code smell.
Here's one way around this:
public class BusinessManager<T> where T : Business, new() {
private readonly T business;
public BusinessManager() {
business = new T();
}
}
but personally I'd prefer
public class BusinessManager<T> where T : Business {
private readonly T business;
public BusinessManager(T business) {
this.business = business;
}
public string GetBusinessName() {
return this.business.GetBusinessName();
}
}
You should do
public class BusinessManager<T> where T : Business, new()
...
T _business = new T();
string businessName = _business.GetBusinessName();
return businessName;
I don't know about C# syntax, but is it not possible to do:
public class BusinessManager<T> where T : Business, new()
{
private T _business;
public string ShowBusinessName()
{
string businessName;
_business = new T();
return _business.GetBusinessName();
}
}
Since other guys have already shown various answers to your first question, I would like to address the second one: design.
1. Role of BusinessManager
Actual role of the BusinessManager class in your example is not too clear. Since this class is generic, and it shouldn't be concerned with the actual type of T, then it does nothing more than add another unnecessary layer between the Business class and the rest of the program.
In other words, you can simply use:
Business casino = new Casino();
Response.Write(casino.GetBusinessName());
Business drugStore = new DrugStore();
Response.Write(drugStore.GetBusinessName());
Wrapping this in another generic class doesn't help you a lot. On the other hand, if you want to have some common functionality for all these classes, you can either add it directly to your abstract class, or extract an interface and create extension methods for that interface.
2. Using properties for getters
Second thing, using a property is more appropriate when you have a simple getter method. In other words, you should replace GetBusinessName() method with a Name property (I also omitted the "Business" from the name because it is not necessary:
public interface IBusiness
{
string Name { get; }
}
public abstract class Business : IBusiness
{
public abstract string Name { get; }
}
public class Casino : Business
{
public override string Name
{
get { return "Casino Corp"; }
}
}
public class DrugStore : Business
{
public override string Name
{
get { return "DrugStore business"; }
}
}
And then you can use it like this:
IBusiness casino = new Casino();
Response.Write(casino.Name);
IBusiness drugStore = new DrugStore();
Response.Write(drugStore.Name);
Also, you can see that I have introduced a IBusiness interface. The reason for doing so is to allow you to implement this interface in more diverse ways. Right now, you will try to derive all your classes from the abstract Business class, and try to extract as much of the common functionality in the abstract class (that's the purpose of the class).
But extracting lots of common functionality comes with a cost: there is always a possibility that you will come up with a need to create a class which isn't derived from Business. If you are accessing all these methods through the IBusiness interface, then other parts of your program won't care if that implementation is derived from Business or not.
Since GetBusinessName really applies to the type and not instances of the type, you might consider using DescriptionAttribute (or your own BusinessNameAttribute) instead of an overridden property and have your BusinessManager get the business name from the attribute.
[Description("Casino Corp")]
public class Casino : Business
{
}
Now you no longer need to instantiate the business just to gets its name. To get the description, you use:
public string ShowBusinessName()
{
var attribute = Attribute.GetCustomAttribute(typeof(T), typeof(DescriptionAttribute)) as DescriptionAttribute;
if (attribute == null)
return "Unknown business";
return attribute.Description;
}
You can do something like this:
if (typeof(T) == typeof(SomeType))
{
// Same
}
define a BusinessManager class as bellow:
public class BusinessManager<T> where T : Business
{
Business biz;
public BusinessManager()
{
biz = new T();
}
public string ShowBusinessName()
{
return biz.GetBusinessName();
}
}
and use it as bellow:
var businessManager = new BusinessManager<Casino>();
Response.Write(businessManager.ShowBusinessName());
var anotherBusinessManager = new BusinessManager<DrugStore>();
Response.Write(businessManager.ShowBusinessName());
The way you using you will lost encapsulation
In VB.net you can use the GetType pseudo-function on a generic type parameter to get a reflection Type object. I would guess C# should have an equivalent. If for whatever reason you can't use something like that, you could create an array of 0 elements of the desired type, and then check the type of that array. That would probably be cheaper than instantiating an element of the unknown type.