My main class Computer interacts with a number of external systems and currently has the logic for getting/updating their info crammed into it.
I want to move the logic for each system to it's own separate class and i've been able to part of the way there but i'm having trouble calling a method on them.
I've only just recently started playing around with generics so this is probably badly written code, apologies for your eyes in advance.
These are my System classes
public class System
{
public string Name { get;set; }
}
public class System<T> : System
{
public virtual T GetData() => default(T);
public virtual void UpdateData() {}
}
public interface ISystem<T>
{
T GetData();
void UpdateData();
}
These are the systems i've created using the System classes:
public class ComplexSystem : ISystem<RegistryKey>
{
public string GetData() => MethodThatGetsRegistryData();
public bool UpdateData() => MethodThatUpdatesRegistry();
}
public class IntSystem : ISystem<int>
{
private int value = 9;
public int GetData() => this.value;
public void UpdateData()
{
this.value = 3;
}
}
public class StringSystem : ISystem<string>
{
private string value = "hello";
public string GetData() => this.value;
public void UpdateData()
{
this.value = "updated";
}
}
and this is how i'm trying to use the whole thing:
public class Computer
{
public List<System> AssociatedSystems = new List<System>();
public Computer()
{
this.AssociatedSystems.Add(new System<ComplexSystem> {Name="ComplexSystem"});
this.AssociatedSystems.Add(new System<IntSystem> {Name="IntSystem"});
this.AssociatedSystems.Add(new System<StringSystem> {Name="StringSystem"});
}
public void UpdateDataWhenComputerIsChanged()
{
// is it possible to loop through them and call UpdateData on each one without know what generic they are?
foreach (var associatedSystem in this.AssociatedSystems)
{
// something like...
associatedSystem.UpdateData();
}
}
}
Which results in
System does not contain a definition for UpdateData() and no extension method could be found
I'm not married to the code above so if there's a better way of doing it i'm all for learning. I'm essentially looking for a way to have a list of classes that contain data logic (like GetData() and UpdateData()) so i don't have to put that logic into my main class (Computer)
So function UpdateData does not exist in System and that is why you cant call it. I would suggest introducing an ISystem interface and put Name (if you need it) and UpdateData in that and let the generic ISystem<T> interface inherit from that.
public interface ISystem
{
string Name {get;set;}
void UpdateData();
}
public interface ISystem<T> : ISystem
{
T GetData();
}
public class Computer
{
public List<ISystem> AssociatedSystems = new List<ISystem>();
.....
foreach (var associatedSystem in this.AssociatedSystems)
{
associatedSystem.UpdateData();
}
}
Yes there are multiple ways to do this. The ones that I can think of are:
Type checking each System in the loop
Adding a Type property to system
Adding a UpdateData(object) or UpdateData(SomeHighLevelType)
If you need more help please specify the nature of your systems. Are they limited to some specific types or you want is extendable for ever and how much speed critical is your project and I can elaborate more
I was experimenting in order to create a little compile-safe helper for mapping between classes.
public class A : IMappableTo<B>, IMappableTo<A>
{
public string Name { get; set; }
}
public class B
{
public string Name { get; set; }
}
public interface IMappableTo<T>
{
}
public static class ExtensionTest
{
public static T MapTo<T>(this IMappableTo<T> source)
{
return default(T); // this does not mind, just for demo purposes
}
}
The intent was to create an extension method able to detect not implemented maps (at compile time).
It worked as expected, but with an unexpected issue.
public static void test()
{
// compiler doesn't complain, but intellisense can't autocomplete it.
var case1 = new A().MapTo<A>().MapTo<B>();
var case2 = new A().MapTo<string>(); // compiler complains, as intended
}
So well, it does compile and work, but Visual Studio (tested with 2015/2017) is unable to autocomplete the extension method. I did some additional tests and it seems to be produced by the fact that class A implements two IMappableTo constructed interfaces. If I remove one, the autocomplete simply works again.
Any idea of how to fix this behaviour or rewrite the code in a manner that cause no further troubles?
I've searched for similar questions/problems on here and can't seem to find a solution that fits.
I currently have a class that it's constructor has one parameter which in turn calls a method which does not have any parameters but instantiates two objects. In the method, DoWork(), the requirements have changed, so I will need to handle other classes/objects, e.g. Building, Vehicle, etc. I am seeking advice on what would one recommend to take in these other objects, e.g. interfaces, generics, etc?
public class Project
{
public Person Person { get; set; } // will need to handle other classes as well
public String Task { get; set; }
// ctor
public Project(string task)
{
Task = task;
DoWork(); // should I handle this method here?
}
// current method
private void DoWork()
{
var work = new Work(this.Task);
Person = new Person(); // this instance of Person could be other objects as noted
Person.Job = work.Assignment;
Person.Site = work.Site;
...
If your classes Person, Building, Vehicle etc. shares some behavior, and the DoWork method only uses this behavior, polymorphism (either abstract class or interface) would be the best solution.
public MyData Data { get; set; }
void DoWork() {
Data.DoStuff();
}
In the case it wouldn't work, you can overload your DoWork method to do different stuff based on the instance, but this would require getting the instance as a parameter.
void DoWork(Person p) {
...
}
void DoWork(Building b) {
...
}
Otherwise, you can either use generics or polymorph on the Object class (and in both cases, deal with unwanted/unexpected types).
if (obj is Person)
...
else if (obj is Building)
...
else
throw new Exception();
If you want to retain the current structure and simply use a generic type instead of always creating a Person, a very straightforward refactoring looks something like this.
Create an abstract base class for the resource (a person, building, vehicle) required for a project.
public abstract class Resource
{
public virtual Assignment Job { get; set; }
public virtual Site Site { get; set; }
}
Create your concrete classes.
public class Person : Resource
{
public Person()
{
}
}
public class Building : Resource
{
public Building()
{
}
}
Now you can make your Project class accept a generic type T instead of Person. In this example, T must be some derived class of Resource and must support a parameterless constructor.
public class Project<T> where T : Resource, new()
{
public T Resource { get; set; } // will need to handle other classes as well
public String Task { get; set; }
// ctor
public Project(String task)
{
Task = task;
}
// current method
public void DoWork()
{
var work = new Work(this.Task);
Resource resource = new T(); // this instance of Person could be other objects as noted
resource.Job = work.Assignment;
resource.Site = work.Site;
// ...
}
}
You create your projects and do work like this.
Project<Person> personProject = new Project<Person>("MyTask");
personProject.DoWork();
Project<Building> buildingProject = new Project<Building>("MyBuildingTask");
buildingProject.DoWork();
You should not call DoWork from the constructor as shown in your code sample. Create the instance first, then call the method.
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.
Overloading constructors and methods seems messy, i.e. simply differentiating them by the order and number of parameters. Isn't there a way, perhaps with generics, to do this cleanly so that, even if you just have one parameter (e.g. string idCode / string status) you could still differentiate them?
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
TheForm tf1 = new TheForm("online", DateTime.Now);
TheForm tf2 = new TheForm(DateTime.Now, "form1");
}
}
public class TheForm
{
public TheForm(string status, DateTime startTime)
{
//...
}
public TheForm(DateTime startTime, string idCode)
{
//...
}
}
}
If you need that many overloads, perhaps your types are handling too much (see Single Responsibility Principle). Personally I rarely need more than one or a few constructors.
You could consider having a Fluent Builder for the class instead, although it's more work. This would allow you to write something like this:
var form = new TheFormBuilder().WithStatus("foo").WithStartTime(dt).Build();
It's more explicit, but not necessary better. It's definitely more work.
In C# 4, you can optionally write the parameter names when you invoke the constructor:
var form = new TheForm(status: "Foo", startTime: dt);
The new object initialization feature of .NET 3.0 is more flexible than an overloaded constructor. Here is a simple example:
public class Item
{
public string Name {get; set;}
public int Index {get; set;}
public string Caption {get; set;}
}
As it is written now, we can do the following in code:
var x = new item {Name=”FooBar”};
var x = new item {Name=”FooBar”, Index=”1”, Caption=”Foo Bar”};
I would only add an overloaded constructor to the class Item if I want to add functionality during property initialization. For example:
public class Item
{
public Item() {}
public Item(string name)
{
Name = name;
Caption = name; //defaulting name to caption
}
public Item(string name, int index) : this(name)
{
Index = index;
}
public Item(string name, int index, string caption) : this(name, int)
{
Caption = caption;
}
public string Name {get; set;}
public int Index {get; set;}
public string Caption {get; set;}
}
Note: If this was a child class, I could have chained to a parent constructor with the “base” keyword.
If I am writing a “configuration” type of class, I use Fluent Methods in place of Overloaded constructors.
For example, if I added these methods to the Item class:
public Item WithName(string name)
{
Name = name;
return this;
}
public Item WithIndex(int index)
{
Index = index;
return this;
}
public Item WithCaption(string caption)
{
Caption = caption;
return this;
}
I could write code like this:
var x = new Item().WithName(“FooBar”).WithIndex(“99”).WithCaption(“Foo Bar”);
The only way I can think of to differentiate the construction with a single parameter of a given type is to use a non-instance factory method, either on the type itself or in a factory class.
e.g. (on the type itself)
(untested)
public class TheForm
{
public static TheForm CreateWithId(string idCode)
{
}
public static TheForm CreateWithStatus(string status)
{
}
}
Before Fluent builders we sometimes managed to get around with parameter objects or setup objects:
public class FormSetup {
public string Status ...
public string Id ...
}
var frm = new MyForm(new FormSetup { Status = "Bla", ... });
Constructor Forwarding!
Use helper initialization classes to communicate the semantics of your overloads.
So, for instance, define
public class TheForm
{
public class TheForm(ById initializer)
{
//...
}
public class TheForm(ByStatus initializer)
{
//...
}
// ...
public class ById
{
public ById(DateTime startTime, string idCode)
// ...
}
public class ByStatus
{
public ByStatus(string status, DateTime startTime)
// ...
}
}
However, prefer using classes which are more generally usable if you can, not just for initalialization. You may want to factor your classes in a different way instead. I sense the possibility of a code smell: does your TheForm class contain too much business logic? Might you want to split out an MVC Controller, for instance?
In C# (like in many other programming languages) in this case you should use Factory Methods. Something like this:
class TheForm
{
public static TheForm CreateFromId(string idCode);
public static TheForm CreateFromStatus(string status);
}
or fiction parameters:
class TheForm
{
public TheForm(string idCode, int);
public TheForm(string status);
}
Or you can use Eiffel ;):
class THE_FORM create
make_from_id, make_from_status
feature
...
end
We use properties instead of overloading constructors, it's quite clean and easy to implement:
public class x {
public string prop1 {get;set;}
public DateTime prop2 {get;set;}
...
}
and then fill just the properties you need at instantiation time (and/or later)
var obj = new x() {
prop1 = "abc",
prop2 = 123
};
The benefit with this is it works with .Net 3.5 and makes it really clear what is being set. (as opposed to var obj = new x("abc", 123, true, false, ... etc) where you have to guess the meaning of each value, which can get really hairy when there are many overloads)
Here's an example:
Timespan.FromMilliseconds(double)
Timespan.FromSeconds(double)
Timespan.FromMinutes(double)
Timespan.FromHours(double)
Timespan.FromDays(double)
Isn't this where inheritence comes in?
Just have TheForm as a base class and then TheFormWithID and TheFormWithStatus child classes.
Have their constructors take string ID and string Status respectively passing back the DateTime value to the base class.
I haven't got any coding tools infront of me so please excuse the syntax. I'm sure that you'll figure it out.
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
TheForm tf1 = new TheFormWithStatus(DateTime.Now, "online");
TheForm tf2 = new TheFormWithID(DateTime.Now, "form1");
}
}
public class TheForm
{
public TheForm(DateTime startTime)
{
//...
}
}
public class TheFormWithID : TheForm
{
public TheFormWithID (DateTime startTime, string idCode) : TheForm (startTime)
{
//...
}
}
public class TheFormWithStatus : TheForm
{
public TheFormWithStatus (DateTime startTime, string status) : TheForm (startTime)
{
//...
}
}
}
Or have TheForm as an abstract class.
Whether you're talking about constructors or not, overloading's pretty limited, and when you start to run up against its limits, that's a hint that it's not the right tool for the job.
It's worth looking at a well-designed API that uses overloading to get a sense of what kind of job the tool is good for. XmlReader.Create is a good example: It supports twelve different overloads. Twelve! And yet, it's actually completely sensible: when you look at them all, they boil down to what would, in Python, be a single calling signature with optional parameters:
XmlReader.Create(input [, settings [, parser_context]])
input, to this method, can be a string containing a URL or filename, a TextReader, or a Stream. But irrespective of its data type, it's still fundamentally the same thing: the source of the data that the XmlReader is going to read.
Now let's look at your case. Forget about data types for a moment. There's clearly some functional difference between a status and an idCode in your application. Your form is going to behave one way if it's given a status and another if it's given an idCode. The API that you're proposing conceals this functional difference. It should be illuminating it.
I would first consider the simplest possible approach, which uses no overloads at all:
TheForm(string idCode, string status)
Make your constructor throw an exception if both values are provided (or if both are null). Note that they're mutually exclusive in the documentation. Call it a day.
My second choice would be:
enum FormType
{
IdCode,
Status
};
TheForm(FormType type, string data)
This is less concise, but it has the very great merit of making the fact that this method supports multiple mutually-exclusive modes explicit.
I called that enum FormType because it seemed like a sensible name, given what I know so far, and the fact that this method's a constructor. But whenever you contemplate creating an enum to determine the type of an instance, you should at least consider the possibility that you should really be creating a type to determine the type of an instance:
class TheFormWhatUsesIdCode : TheForm {...}
class TheFormWhatUsesStatus : TheForm {...}
The functional difference between idCode and status probably relates to a functional difference between a form instantiated with idCode and a form instantiated with status. And that strongly suggests that they should be subclasses.
In all of this analysis, I've never once considered the possibility of doing what you actually asked for, which is to provide multiple overloads. I don't think overloading is the right tool for this job. If idCode were an int and status were a string I still wouldn't think that overloading were the right tool for this job, though I probably wouldn't have ended up noticing it until I had a lot of code I needed to refactor.
I am not getting what "messy" you found in multiple constructors. I felt the static methods for returning an instance of the object also a probable alternate.
But, if somebody want to have the fancy of a single constructor and still have different implementations, we can think of passing an object derived from some interface as the input to the constructor and might check the type of the input to create an instance. This is kind of an abstract factory in this case.
In one place we have a class like the following:
using System;
namespace MyApplication
{
class Program
{
static void Main(string[] args)
{
base1 t1 = new type1();
class1 c1 = new class1(t1);
base1 t2 = new type2();
class1 c2 = new class1(t2);
//.....
}
}
public class class1
{
public class1(base1 mytype)
{
switch(mytype.type)
case mytype.types.type1
return createObjectOftype1();
case mytype.types.type2
return createObjectOftype2();
case mytype.types.type3
return createObjectOftype3();
}
public class1 createObjectOftype1()
{
//....
}
public class1 createObjectOftype2()
{
//...
}
public class1 createObjectOftype2()
{
//...
}
}
public class base1
{
publlic Enum Types {0 "type1",....
}
public class type1:base1
{
//.....
}
public class type2:base1
{
//.....
}
}
I personally dont like the idea of other classes being able to set my properties
so this allows my properties to be protected or private, but still have alot of the functionality described by other answers:
public class FooSettings
{
public bool Prop1 { get; set; }
public bool Prop2 { get; set; }
public TimeSpan Prop3 { get; set; }
public FooSettings()
{
this.Prop1 = false;
this.Prop2 = false;
this.Prop3 = new TimeSpan().ExtensionMethod(CustomEnum.Never);
}
public FooSettings BoolSettings
(bool incomingFileCacheSetting, bool incomingRuntimeCacheSetting)
{
this.Prop1 = incomingFileCacheSetting;
this.Prop2 = incomingRuntimeCacheSetting;
return this;
}
public FooSettings Prop3Setting
(TimeSpan incomingCustomInterval)
{
this.Prop3 = incomingCustomInterval;
return this;
}
public FooSettings Prop3Setting
(CustomEnum incomingPresetInterval)
{
return this.Prop3Setting(new TimeSpan().ExtensionMethod(CustomEnum.incomingPresetInterval));
}
}
public class Foo
{
public bool Prop1 { get; private set; }
public bool Prop2 { get; private set; }
public TimeSpan Prop3 { get; private set; }
public CallTracker
(
FooSettings incomingSettings
)
{
// implement conditional logic that handles incomingSettings
}
}
could then be consumed as:
FooSettings newFooSettings = new FooSettings {Prop1 = false, Prop2 = true}
newFooSettings.Prop3Setting(new TimeSpan(3,0,0));
Foo newFoo = new Foo(newFooSettings)
or
FooSettings newFooSettings = new FooSettings()
.BoolSettings(false, true)
.Prop3Setting(CustomEnum.Never)
Foo newFoo = new Foo(newFooSettings)
obviously a bit overkill for a simple class, but it gives alot of control over the types of data that can be funneled down to a single property, IE: TimeSpan can be parsed from a custom enum type using an extension method