So, I want to create an interface which has a method that can take in any model class. For example
I have these three property class
class A
{
public long id { get; set; }
public string description { get; set; }
public string code { get; set; }
}
class B
{
public long someID { get; set; }
}
class C
{
public long anydesign { get; set; }
}
class D
{
public long Router { get; set; }
}
I have an interface
public interface IModel
{
void Dosomething(A model); // Now in this example it takes the A model,But I want it to be set, so that that class that implements the interface can put any model as required
}
Now, I have a class that implements the mode Since the interface only takes the A model, I can pass in the A model in the class during implementation
public class ImplemenationA: IModel
{
public void Dosomething(A model)
{
Console.WriteLine(model.description);
}
}
Say i have another implemenation Class Now, I am guessing the below one wouldnt work, as the interface signature enforces only to take a Model A and not any other model
public class ImplementationB:IModel
{
public void Dosomething(B model)
{
Console.WriteLine(model.someID);
}
}
I want to the interface method to be invoked by any implementation class and use any model
Based on your description you may want to use Generics. Since you're creating separate implementations you can apply the interface below to achieve a similar result.
public interface IModel<T>
{
void Dosomething(T model);
}
public class ImplementationB : IModel<B>
{
public void Dosomething(B model)
{
Console.WriteLine(model.someID);
}
}
Some sort of Decorator pattern can solve it, postpone your actual implementation to inner classes and insist on separation of concern, please leave a comment if I miss understood your question:
//added to support inner implementation
interface IModelImpl {
void Do();
}
class A: IModelImpl
{
public long id { get; set; }
public string description { get; set; }
public string code { get; set; }
public void Do(){
console.WriteLine(this.description);
}
}
class B: IModelImpl
{
public long someID { get; set; }
public void Do(){
console.WriteLine(this.someID);
}
}
class C: IModelImpl
{
public long anydesign { get; set; }
public void Do(){
...
}
}
Here is your IModel, pretty much the same, considered like an outer implementation:
public interface IModel
{
void Dosomething(IModelImpl model); //put any model as long it implements IModelImpl
}
Your class implementation should now changed to:
public class ImplemenationA: IModel
{
public void Dosomething(IModelImpl model)
{
//Do more specific work to ImplementationA
model.Do();
}
}
Another class implementation:
public class ImplementationB:IModel
{
public void Dosomething(IModelImpl model)
{
//Do more specific work to ImplementationB like validation
model.Do();
}
}
Related
Say I have the following classes:
public abstract class A
{
protected abstract ReturnA Foo();
public void UseFoo()
{
var foo = Foo();
if (foo != null)
{
//logic here
}
}
}
public class B : A
{
protected override ReturnA Foo()
{
// Implementation specific code that returns ReturnB instead.
}
}
public class C : A
{
protected override ReturnA Foo()
{
// Implementation specific code that returns ReturnC instead.
}
}
public class ReturnA
{
public int Id { get; set; }
public string Address { get; set; }
}
public class ReturnB
{
public string Id { get; set; }
public string PhoneNumber { get; set; }
}
public class ReturnC
{
public Guid Id { get; set; }
public string Name { get; set; }
}
I know that C# does not support derived return types, but this is not what I need either.
Classes B and C are implementation specific and therefore their return types have nothing to do with eachother.
The reason why I would want to handle this, is because the method UseFoo in class A may have some generic checks and other generic logic, that has nothing to do with the returned object itself.
So I want to "outsource" only the code that is implementation specific and not have to instead make UseFoo abstract and have every implementation write the same generic code.
Is there any way to solve this at all?
EDIT: Neither ReturnC nor ReturnB are derived from ReturnA. Updated with examples.
So, I want to create an interface which has a method that can take in any model class.
For example
I have these three property class
class A
{
public long id { get; set; }
public string description { get; set; }
public string code { get; set; }
}
class B
{
public long someID { get; set; }
}
class C
{
public long anydesign { get; set; }
}
class D
{
public long Router { get; set; }
}
I have an interface
public interface IModel
{
void Dosomething(A model); // Now in this example it takes the A model,But I want it to be set, so that that class that implements the interface can put any model as required
}
Now, I have a class that implements the mode
Since the interface only takes the A model, I can pass in the A model in the class during implementation
public class ImplemenationA: IModel
{
public void Dosomething(A model)
{
Console.WriteLine(model.description);
}
}
Say i have another implemenation Class
Now, I am guessing the below one wouldnt work, as the interface signature enforces only to take a Model A and not any other model
public class ImplementationB:IModel
{
public void Dosomething(B model)
{
Console.WriteLine(model.someID);
}
}
I want to the interface method to be invoked by any implementation class and use any model
While it is unjustified what you're attempting to do... to answer the actual question it is possible using generics...
Take the following for guidance (and example)...
class Test : IJobTask
{
public void Start(string val = "")
{
throw new NotImplementedException();
}
}
public interface ITest
{
void MyMethod<T>(T model) where T : IJobTask;
}
public class ConcreteTest : ITest
{
public void MyMethod<T>(T model) where T : IJobTask
{
}
}
public class Main
{
public Main()
{
var ct = new ConcreteTest();
ct.MyMethod(new Test());
}
}
Your MyMethod will need to perform checks and casts now which kind of defeats the purpose, but this does answer the question of "a method accepting any model"
Use interface for your property classes.
public interface IProperty
{
...
}
class A: IProperty
{
...
}
class B: IProperty
{
...
}
class C: IProperty
{
...
}
class D: IProperty
{
...
}
And then you can pass interface as a parameter:
public interface IModel
{
int getModel(IProperty model);
}
I can't use override since the types don't match and I've read I shouldn't use new to hide it, so how would I accomplish this?
SearchBase and ResultBase will work for 80% of my entities but a few will need specific implementations.
This main problem I see is when I do use new it's all typed during compile time and looks good in the debugger but passing this object to System.Web.Mvc.Controller.Json() seems to have a problem serializing it and they come out null.
public class SearchBase<T>
{
public virtual ResultBase result { get; set; }
}
public class SearchImp : SearchBase<SearchImp>
{
public override ResultImp result { get; set; }
}
public class ResultBase
{
}
public class ResultImp : ResultBase
{
}
You could use this instead:
public class SearchBase<T, TResult> where T: ResultBase
{
public TResult result { get; set; }
}
public class SearchImp : SearchBase<SearchImp, ResultImp>
{
public TResult result { get; set; }
}
public class ResultBase
{
}
public class ResultImp : ResultBase
{
}
This way you don't need to override anything (nothing really to override here) and you can keep it type-safe.
I'm currently on design stage in writing C# .NET Core application. I'm gonna use the generics to inherit some properties among all derived classes. The goal is to archive many 2 many relation of entities able to be tagged. The app concept is funky, because tag will contain related logic as constraint entity. I have problems with the proper where statements in generic class, to be able to use inherited Tags property for all Taggable Entities.
Here is abstraction:
public interface ITaggable
{
long TagId { get; set; }
Tag Tag { get; set; }
}
public interface IEntityTag<T> : ITaggable where T : Entity
{
long EntityId { get; set; }
T Entity { get; set; }
}
public abstract class TaggableEntity<T> : Entity where T : ITaggable
{
public ICollection<T> EntityTags { get; set; }
public List<Tag> Tags { get { return EntityTags.Select(x => x.Tag).ToList(); } }
}
public abstract class ConstraintBase<TSubject, TOwner>
: ConstraintEntity where TOwner : TaggableEntity<IEntityTag<TOwner>>
{
protected ConstraintBase(ConstraintId id, string description)
{
Id = id.Value();
Name = id.ToString();
Description = description;
IsExecutable = false;
}
public IEnumerable<TSubject> Validate(IEnumerable<TSubject> items, TOwner owner)
{
return items.Where(x => Validate(x, owner));
}
public void Execute()
{
if (IsExecutable) { OnExecuting(); }
}
protected abstract bool Validate(TSubject item, TOwner owner);
public abstract void OnExecuting();
}
And here concrete classes.
public class ConstraintEntity : Entity
{
public string Name { get; set; }
public string Description { get; set; }
public bool IsExecutable { get; set; }
public ConstraintId ConstraintId => (ConstraintId)Id;
}
public class EndWorkConstraint : ConstraintBase<Activity, User>
{
public EndWorkConstraint() : base(ConstraintId.EndWorkConstraint, "Check if user is allowed to end work")
{
}
protected override bool Validate(Activity item, User owner)
{
return item.ActivityId != ActivityId.EndWork;
}
public override void OnExecuting()
{
throw new System.NotImplementedException();
}
}
public class User : TaggableEntity<UserTag>
{
public string Login { get; set; }
public string Password { get; set; }
}
The question is: am I able to modify ConstraintBase where statement, to make EndWorkConstraint class do not raising an error, and still have the tags explicit avalible?
This is my first post on the forum, and I m really forced to use Yours wisdom. I'd be glad for any tips. Thanks in advance.
I have class:
internal class Stage
{
public long StageId { get; set; }
public string StageName { get; set; }
public int? Order { get; set; }
public Stage()
{
Order = 0;
}
}
I have also:
public class GroupStage : Stage
{
private override long StageId { set { StageId = value; } }
public GroupStage() : base() { }
public void InsertStage(long groupId)
{
}
public static void SetStageOrder(long stageId, int order)
{
....
}
public static void DeleteStage(long stageId)
{
....
}
public static GroupStage[] GetStages(long groupId)
{
....
}
}
and:
public class TaskStage : Stage
{
public DateTime? Time { get; set; }
public TaskStage()
: base()
{
....
}
public static Stage GetNextTaskStage(Guid companyId, long taskId)
{
....
}
public static Stage[] GetTaskStages(Guid companyId, long taskId)
{
....
}
}
This is not working and I get the exception:
Inconsistent accessibility: base class Stage is less accessible than class GroupStage
I want Stage class to be private and without access except to GroupStage and TaskStage. I also want to make StageId be private in GroupStage and in TaskStage.
How can I do that without duplicate the members of Stage in GroupStage and in TaskStage?
You can't make a derived class more accessible than it's base class. What you can do is make TaskStage and GroupStage internal as well, then inherit and expose public interfaces so that only the interface is visible outside of your assembly.
public interface IGroupStage
{
public string StageName{ get; set; }
...
}
interal class GroupStage : IGroupStage
{
...
}
You need to make you Stage class public or protected. if you make it abstract it cant be instantiated on that level, so if its public you dont have to worry about it being created as a base class
Make it protected instead of private. If you make it protected, you let classes that inherit from it call methods on the base class, and inherit the base class members.
What you probably actually want is for Stage to be an abstract base class which, therefore, cannot directly be instantiated regardless of its accessibility modifier. Change your definition of Stage:
public abstract class Stage
{
protected long StageId { get; set; }
public string StageName { get; set; }
public int? Order { get; set; }
protected Stage()
{
Order = 0;
}
}
The protected modifier means that your derived classes will be able to access that member, but it will not be accessible outside those classes.