I came to this situation in the process of refactoring my project.
There's a model class, which contains several submodels:
public class Model
{
public Submodel_A SM { get; set; }
public Submodel_B SM { get; set; }
public Submodel_C SM { get; set; }
}
public class Submodel_A { /* contains only properties */ }
public class Submodel_B { /* contains only properties */ }
public class Submodel_C { /* contains only properties */ }
Now, I need to move the Model to a separate assembly. To do so, I'd like the model to implement an interface, say, IModel. But here I'm stuck, because of the submodels:
interface IModel
{
Submodel_A SM { get; set; }
Submodel_B SM { get; set; }
Submodel_C SM { get; set; }
}
Obviously, using Submodel_* classes themselves is not a solution. Do I really have to have an interface per submodel? Or, maybe, it's better to hide them from the interface somehow? (Hiding is an option, since submodels only carry some data and have virtually no other functionality).
Basically, I ended up in having interfaces for everything, gathered in a dedicated assembly. Yes, almost all other modules depend on it now, but it hasn't brought any trouble so far...
Related
I have a base class for all the ENTITIES of my project which is inheriting from below model :
public class BaseModel
{
public int Id { get; set; }
public int CreatedDate { get; set; }
public override string ToString();
}
Now I have 1 another functionality which is common for so many modules and I want to keep BaseModel for that functionality and want it to be inherited from it.
Public class BaseNotice
{
// Common info related to notice which is use to send notice to employees in different scenarios
}
Now our every model is suppose to inherit from BaseModel so inheriting from BaseNotice will be multiple inheritance.
Now I cannot like below :
Public class BaseNotice : BaseModel
{
// Common info related to notice which is use to send notice to employees in different scenarios
}
Because I would like to control functionality related to Notice from BaseNotice model and for notice I would like to keep BaseNotice as base model.
But I am not getting how to avoid multiple inheritance here and so what would be the proper way to design this?
There is No need to Multiple Inheritance. you can do that in this way:
public class BaseModel
{
public int Id { get; set; }
public int CreatedDate { get; set; }
public override string ToString();
}
public interface IBaseNotice
{
// Base Notices Contracts should be placed here
}
Public class BaseNotice: IBaseNotice
{
// Common info related to notice which is use to send notice to employees in different scenarios
}
public class ModelX:BaseModel
{
public IBaseNotice Notice { get ; set; }
public ModelX(IBaseNotice baseNotice)
{
Notice = baseNotice;
}
}
Or you can use Second Generation of your BaseModel:
public class BaseModeNoticable:BaseModel
{
public IBaseNotice Notice { get ; set; }
public BaseModeNoticable(IBaseNotice baseNotice)
{
Notice = baseNotice;
}
}
I have two classes below, Form and FormFieldOption<T>. The latter is intended to represent a set of <option> inside of a <select> in a web form that the Form object represents.
public class Form
{
public int Id { get; set; }
public FormFieldOption<string> Status { get; set; }
public FormFieldOption<string> Category { get; set; }
public FormFieldOption<int> Severity { get; set; }
}
public class FormFieldOption<T>
{
public int Id { get; set; }
public string Description { get; set; }
public bool Active { get; set; }
public T Value { get; set; }
}
I'm working on configuring these entities for Code-First like below:
public class FormFieldOptionStringConfiguration : EntityTypeConfiguration<FormFieldOption<string>>
{
public FormConfiguration()
{
//configure here
}
}
Unfortunately at this point I've discovered that I would like there to be a difference between the configuration for the Status and Category properties. I've not been able to figure out a way top configure the properties that utilize the FormFieldOption class individually. How could I do this?
Solutions I've come up with:
Create a new class that inherets FormFieldOption<T> for each property and configure individually.
Create an interface IFormFieldOption<T> and implement classes individually for each use.
I don't particularly care for either of these options as it feels like a lot of duplicated code just to create a different configuration for each table.
It turns out that you can't do this. What I ended up doing was creating a generic interface that I implemented for each property.
I'm looking for a class structure or design pattern to implement a base class that has a list of "base items", where several derived classes have the same list but that list is of derived "base items".
Here's a vastly stripped down example (ignore the accessibility of properties, they wouldn't actually all have public setters and default constructors):
public class BaseTransaction {
public List<BaseTransactionItem> Items { get; set; }
public void AddItem(string description, int quantity, decimal price)
{
// Add a new BaseTransactionItem to Items
}
}
public class BaseTransactionItem {
public string Description { get; set; }
public int Quantity { get; set; }
public decimal Price { get; set; }
}
public class OrderTransaction : BaseTransaction {
public List<OrderTransactionItem> Items { get; set; }
public int Deposit { get; set; }
public void SetDeposit(int depositAmount)
{
// Do some stuff to set the deposit.
}
}
public class OrderTransactionItem : BaseTransactionItem
{
public int QuantityFulfilled { get; set; }
}
public class RetailTransaction : BaseTransaction {
public List<RetailTransactionItem> Items { get; set; }
public List<Tender> Tenders { get; set; }
public void AddTender(Tender tender)
{
// Add a tender to the RetailTransaction
}
public decimal TotalTax
{
get { return Items.Sum(i => i.Tax); }
}
}
public class RetailTransactionItem : BaseTransactionItem
{
public decimal Tax { get; set; }
}
The way I need to work with these classes is that you start with a BaseTransaction and add some items to it, and then it can become either an OrderTransaction or a RetailTransaction. These both share most of their logic and properties with a BaseTransaction but have specific extra fields and methods, as well as the List<BaseTransactionItem> becoming a List<OrderTransactionItem> or a List<RetailTransactionItem> respectively.
Further more, after a BaseTransaction is "promoted" to a RetailTransaction, it may be "demoted" back to a BaseTransaction and then "promoted" to an OrderTransaction (but never from a RetailTransaction to an OrderTransaction in this case).
I've tried several approaches to this, with generics, the Decorator pattern (which doesn't seem appropriate), TypeConverters, and yet nothing seems to fit. The only possible solution I've thought of that works is having the RetailTransaction class have a constructor that takes a BaseTransaction and copying over all the properties and converting the list using .Cast<RetailTransactionItem> but this will make maintaining the derived classes pretty difficult.
If it wasn't for the list type needing to change this would be a simple case of using inheritance. I'm completely open to alternative approaches such as those favouring composition over inheritance but since the RetailTransaction and OrderTransaction classes truely are more specific versions of BaseTransaction, inheritance seems to fit - at least in my mind.
I am building a windows service that will act as a client to an existing site that's employing SignalR.
I have IHubProxy.On<> and IHubProxy.Invoke methods working when passing around concrete classes.
For example, this works:
hubProxy.On<MigrationRequest>("iSWindowsServiceRequest", request =>
MigrateData.Invoke(request));
And the MigrationRequest looks like this:
public class MigrationRequest : IISWindowsServiceRequest
{
public MigrateWhat What { get; set; }
public MigrationFor For { get; set; }
public Guid EntityFor_Id { get; set; }
}
Now, If i try this:
hubProxy.On<IISWindowsServiceRequest>("iSWindowsServiceRequest", request =>
Handshake.HandleRequest(request));
my request is never picked up.
what I was hoping to achieve was creating single pub-sub methods, rather than one for each concrete class that this service would accept.
Is it possible to pass in an interface into the On<>() methods?
The same goes for the Invoke<>() - if the object I am passing contains any properties that are of an interface, the call never makes it.
so this will not work:
public class ISWindowsServiceResponse
{
public IISWindowsServiceRequest OriginalRequest { get; set; }
public bool Success { get; set; }
public string Message { get; set; }
}
but this will
public class ISWindowsServiceResponse
{
public MigrationRequest OriginalRequest { get; set; }
public bool Success { get; set; }
public string Message { get; set; }
}
Where I work, we spent a lot of time trying to figure out a way to get SignalR hubs to serialize interfaces. In the end, we wound up having to extract real objects (real classes and structs, not behind an interface) to send over the wire. There is no way to tell SignalR how to serialize an interface.
I have a system that performs operations on lots of Things, these can be considered to be hardware devices accessible over a communication channel.
I use a manager construct that accepts tasks for single Things. Now, there are at least three types of Thing and they have slightly different properties associated with them. The manager must know about these extra properties as they are needed to perform any operation correctly (some Things must have their X foo'd instead of their Y etc...).
At the moment I have separate manager class for each type of thing. This causes a good deal of duplication as the Things are mostly similar.
It would be good if I could have an abstract manager that implements a good deal of the functionality and then each concrete implementation can supply the little extra bits.
Here is a greatly simplified example:
public abstract class ThingManager
{
private ConcurrentDictionary<Guid, ??ThingTask??> _ThingTaskQueue;
public virtual AddNewThingTask(<params>)
{
??ThingTask?? NewTask = new ??ThingTask??(<params>);
_ThingTaskQueue.Add(NewTask);
Monitor.Pulse(_NewDataToProcess);
}
/* Implemented by the concrete, will depend on the type of ??ThingTask?? */
public abstract GetSomeTaskParameterForAThing(Guid thingID)
}
public class ThingTask
{
public enum ThingOperation
{
Foo,
Bar
};
public String Name { get; set; };
public ThingType Type { get; set; };
public ThingOperation Operation { get; set; }
}
public class AdvancedThingTask
{
public enum ThingOperation
{
Foo,
Bar,
Baz
};
public String Name { get; set; };
public ThingType Type { get; set; };
public ThingOperation Operation { get; set; }
public Boolean EnableFrobber { get; set; }
}
As you can see I need some way, when defining the concrete ThingManager to have ??ThingTask?? be either a ThingTask or an AdvancedThingTask. It would then be up to the concrete to make use of the extra properties when implementing the abstract methods.
Using an interface for ??ThingTask?? wouldn't work because the properties would have to be declared in the interface and each one has different properties available.
I get the feeling I'm missing something very obvious as to how to do this cleanly, hopefully someone can help :)
use generics rather than a pure abstract class, someting along the lines of:
public abstract class ThingManager<T> where T : ThingTask
dependant on your full implementation I doubt if this will need to remain abstract
Is there any reason you don't make AdvancedThingTask a subclass of ThingTask?
public class ThingTask
{
public virtual string Name { get; set; }
public virtual ThingType Type { get; set; }
public virtual ThingOperation Operation { get; set; }
public virtual void DoThing() { /*Do something associated with ThingTask*/ }
}
public class AdvancedThingTask : ThingTask
{
public bool EnableFrobber { get; set; }
public override void DoThing() { /*Do something associated with AdvancedThingTask*/ }
}
The only problem I see with this is that ThingOperation will need to be declared outside of the classes so that it can have all the values, or some other solution that will enable classes to have values that aren't in the base declaration. That problem may be solved by putting what you want to do as virtual methods in the classes.
P.S. Why do your properties start with underscores? Usually that's reserved for private variables.