I have the following code which is fine...
namespace GenericAbstract
{
public interface INotifModel
{
string Data { get; set; }
}
public interface INotif<T> where T: INotifModel
{
T Model { get; set; }
}
public interface INotifProcessor<in T> where T : INotif<INotifModel>
{
void Yell(T notif);
}
public class HelloWorldModel : INotifModel
{
public string Data { get; set; }
public HelloWorldModel()
{
Data = "Hello world!";
}
}
public class HelloWorldNotif : INotif<HelloWorldModel>
{
public HelloWorldModel Model { get; set; }
public HelloWorldNotif()
{
Model = new HelloWorldModel();
}
}
public class HelloWorldProcessor<T> : INotifProcessor<T> where T : INotif<INotifModel>
{
public void Yell(T notif)
{
throw new NotImplementedException();
}
}
}
As you can see there are 3 interfaces and each of those is implemented.
However, I would like the processor to be implemented like this:
public class HelloWorldProcessor : INotifProcessor<HelloWorldNotif<HelloWorldModel>>
{
public void Yell(HelloWorldNotif<HelloWorldModel> notif)
{
throw new NotImplementedException();
}
}
But i get the following error:
The non-generic type 'HelloWorldNotif' cannot be used with type arguments
I want the HelloWorldProcessor to implement INotifProcessor only for HelloWorldNotif...
Can't figure out what I am doing wrong..
For this to work you first have to make INotif<T> co-variant. That means that the Model property has to be read only for the interface (it can still have a public set in an implementation). Then to fix your immediate error you don't put the <HelloWorldModel> after HelloWorldNotif because it's already a INotif<HelloWorldModel>
public interface INotifModel
{
string Data { get; set; }
}
public interface INotif<out T> where T : INotifModel
{
T Model { get; }
}
public interface INotifProcessor<in T> where T : INotif<INotifModel>
{
void Yell(T notif);
}
public class HelloWorldModel : INotifModel
{
public string Data { get; set; }
public HelloWorldModel()
{
Data = "Hello world!";
}
}
public class HelloWorldNotif : INotif<HelloWorldModel>
{
public HelloWorldModel Model { get; set; }
public HelloWorldNotif()
{
Model = new HelloWorldModel();
}
}
public class HelloWorldProcessor<T> : INotifProcessor<T> where T : INotif<INotifModel>
{
public void Yell(T notif)
{
throw new NotImplementedException();
}
}
public class HelloWorldProcessor : INotifProcessor<HelloWorldNotif>
{
public void Yell(HelloWorldNotif notif)
{
throw new NotImplementedException();
}
}
Then I guess your implementation would be something like
Console.WriteLine(notif.Model.Data);
As others have said and/or implied out you've already got HelloWorldNotif fully specified. So to translate this:
I want the HelloWorldProcessor to implement INotifProcessor only for
HelloWorldNotif
To C#, I think you mean:
public class HelloWorldProcessor : INotifProcessor<HelloWorldNotif>
{
public void Yell(HelloWorldNotif notif)
{
throw new NotImplementedException();
}
}
Related
Suppose I have two classes and both contain the same fields
Class A
{
public string Name { get; set; }
public int Designaton { get; set; }
}
Class B
{
public string Name { get; set; }
public int Designation { get; set; }
}
And I have one interface and two classes which are inherited from interface
public interface IDeprt
{
object BindData();
}
And two extractor classes:
public classAItem : IDeprt
{
public object BindData()
{
return new A()
{
// mapping operation
}
}
}
public classBItem : IDeprt
{
public object BindData()
{
return new B()
{
//same mapping operation
}
}
}
My question, how can I implement this in generic way using <T> .
Both classes are doing same operation only return type change. If I am doing in the above way there is lot of duplication of code.
Make your ITem interface and also BindData generic make them use the same generic parameter.
public interface IItem<T>
{
T BindData();
}
Then implement the subclasses like below :
public class AItem : ITem<A>
{
public A BindData(){
return new A(){
// mapping operation
}
}
}
public class BItem : ITem<B>
{
public B BindData(){
return new B(){
//same mapping operation
}
}
}
Edit : As the question evolves.
Make a shared base class for A and B classes.
public abstract class CommonItem
{
public string Name { get; set; }
public int Designaton { get; set; }
}
class A : CommonItem
{
}
class B : CommonItem
{
}
Then make class with a method that accepts a generic parameter with new and CommonItem constraints.
public class Binder
{
public T BindData<T>() where T: CommonItem, new()
{
return new T()
{
// you can access the properties defined in ICommonItem
}
}
}
Usage :
var binder = new Binder();
var boundA = binder.BindData<A>();
var boundB = binder.BindData<B>();
I have the following interfaces, one for the entity and one for some logic:
public interface IItem
{
int Id { get; set; }
}
public interface IGenerator
{
IList<IItem> Generate();
}
and implementation:
public class ItemA : IItem
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ItemAGenerator : IGenerator
{
public IList<ItemA> Generate()
{
// do stuff
return List<ItemA>;
}
}
That implementation did not work, it says that it does not have the matching return type, so I also tried:
public class ItemAGenerator : IGenerator
{
public IList<IItem> Generate()
{
// do stuff
return List<ItemA>;
}
}
it does not work as well, it says: cannot implicitly convert type List<IItem> to List<ItemA>.
How to make it work? what am I missing here.
Just create the list as a List<IItem> but add ItemA's to it.
public class ItemAGenerator : IGenerator
{
public IList<IItem> Generate()
{
var list = new List<IItem>();
list.Add(new ItemA());
return list;
}
}
Just make IGenerator generic. Then you can specify the type that will be returned.
public interface IGenerator<T> where T : IItem
{
IList<T> Generate();
}
public class ItemAGenerator : IGenerator<ItemA>
{
public IList<ItemA> Generate()
{
// do stuff
return List<ItemA>;
}
}
I've written a code as below. In this code I want to put a constraint on ServiceResult and BaseService classes so that T needs to implement IBaseEntity interface.
Here is the code:
public interface IBaseEntity
{
int Id { get; set; }
}
public class Photo : IBaseEntity
{
public int Id { get; set; }
public float FileSize { get; set; }
public string Url { get; set; }
}
public class ServiceResult<T> where T : class, IBaseEntity, new()
{
public bool Succeed { get; set; }
private T data;
public T Data
{
get
{
if (data == null)
data = new T();
return data;
}
set
{
data = value;
}
}
}
public abstract class BaseService<T> where T : class, IBaseEntity, new()
{
public abstract ServiceResult<List<T>> GetAll();
public abstract ServiceResult<T> GetById(int Id);
}
public class PhotoService : BaseService<Photo>
{
public override ServiceResult<List<Photo>> GetAll()
{
throw new Exception();
}
public override ServiceResult<Photo> GetById(int Id)
{
throw new Exception();
}
}
public class Program
{
public static void Main(string[] args)
{
Console.ReadKey();
}
}
In the code I get the error as below (error refers to GetAll() methods)
Error 3 The type
'System.Collections.Generic.List' cannot be used
as type parameter 'T' in the generic type or method
'FOC.Session04.ServiceResult'. There is no implicit reference
conversion from 'System.Collections.Generic.List'
to 'FOC.Session04.IBaseEntity'. G:\Courses\ASP.NET MVC5\Session4
960803\FOC.Session04\FOC.Session04\Program.cs 55 52 FOC.Session04`
But when I remove the interface constraint IBaseEntity from ServiceResult class and let it remain after BaseService I will get no error and the code compiles without error.
Can anybody explain me why I can't add constraint after ServiceResult class?
What's the reason? Or which part of code need to be changed in order to compile error less in this case?
Thanks all
I think you want rather
public abstract List<ServiceResult<T>> GetAll();
instead of
public abstract ServiceResult<List<T>> GetAll();
List<T> does not even match your constraints (hence the compiler error)
What you really need is for GetAll to return a List of ServiceResults, like so
public interface IBaseEntity
{
int Id { get; set; }
}
public class Photo : IBaseEntity
{
public int Id { get; set; }
public float FileSize { get; set; }
public string Url { get; set; }
}
public class ServiceResult<T> where T : class, IBaseEntity, new()
{
public bool Succeed { get; set; }
private T data;
public T Data
{
get
{
if (data == null)
data = new T();
return data;
}
set
{
data = value;
}
}
}
public abstract class BaseService<T> where T : class, IBaseEntity, new()
{
public abstract List<ServiceResult<T>> GetAll();
public abstract ServiceResult<T> GetById(int Id);
}
public class PhotoService : BaseService<Photo>
{
public override List<ServiceResult<Photo>> GetAll()
{
throw new Exception();
}
public override ServiceResult<Photo> GetById(int Id)
{
throw new Exception();
}
}
public class Program
{
public static void Main(string[] args)
{
Console.ReadKey();
}
}
I made a look at the source again and understood what is going on.
Putting IBaseEntity constraint on BaseService class has no problem. Because T represents a single class here (PhotoService : BaseService<Photo>). So T is Photo and Photo implements IBaseEntity.
But for GetAll() method in BaseService class the return type is ServiceResult<List<T>>. Therefore in ServiceResult class T will be something like List<Photo> and List<Photo> doesn't implement IBaseEntity. Therefore it raises an error.
Removing IBaseEntity constraint from ServiceResult class solves the problem.
I have a class that looks like:
public class InvokeProxy : MarshalRefByObject, IFace
{
public InvokeProxy(IFace face)
{
this.Face = face;
}
private IFace Face { get; set; }
public string Execute(string data)
{
return this.Face.Execute(data)
}
}
And I'm tasked with making it generic. Since I can't inherit from the generic class, I'm somewhat stuck, does anyone know a workaround?
I'm not really sure what you're looking to do by making InvokeProxy into InvokeProxy<T>...does this help?
public class InvokeProxy<T> : MarshalRefByObject, IFace where T : IFace
{
public InvokeProxy(T face)
{
this.Face = face;
}
private T Face { get; set; }
public string Execute(string data)
{
return this.Face.Execute(data);
}
}
Not really sure if I understood the question....
public class InvokeProxy<T> : MarshalRefByObject where T : class
{
public InvokeProxy(T face)
{
this.Face = face;
}
private T Face { get; set; }
public string Execute(string data)
{
return this.Face.Execute(data)
}
}
I wrote a nested class which is used as a bag for properties. This class is used as property which I named Properties. I want to extend number of properties by interfaces.
I wrote this example:
public interface IFirst {
int asd { get; set; }
}
public interface ISecond {
int zxc { get; set; }
}
public class MyClass {
public class PropertyClass : IFirst {
public int asd {
get {
throw new NotImplementedException();
}
set {
throw new NotImplementedException();
}
}
}
public PropertyClass Properties;
}
public class MyNextClass : MyClass {
public class PropertyClass : MyClass.PropertyClass, ISecond {
public int zxc {
get {
throw new NotImplementedException();
}
set {
throw new NotImplementedException();
}
}
}
public void test() {
Properties.zxc = 5; // Here is problem
}
}
But in this case I cant to read/write new property zxc.
I think because this still is reading a Properties type from parent class - MyClass.PropertyClass and not MyNextClass.PropertyClass.
I want to extending this without creating new property or hiding existing.
Do you have any suggestions?
You'll have to either ensure that the parent class implements both interfaces, or you'll have to create a new static member in the child class that is of the the nested child type. As you surmise, Properties is declared as being of the parent nested type, and declaring a new type in the child class of the same name that derives from the parent nested type doesn't change that.
Well, depending on what you’re trying to achieve approaches may vary. For instance, using abstract class might feet your needs. Like this:
public interface IFirst
{
int asd { get; set; }
}
public interface ISecond
{
int zxc { get; set; }
}
public abstract class MyAbstractClass<T> where T : class
{
public abstract T Properties {get; set;}
}
public class MyClass : MyAbstractClass<MyClass.PropertyClass>
{
public class PropertyClass : IFirst
{
public int asd
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
}
public override MyClass.PropertyClass Properties
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
}
public class MyNextClass : MyAbstractClass<MyNextClass.PropertyClass>
{
public class PropertyClass : MyClass.PropertyClass, ISecond
{
public int zxc
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
}
public override MyNextClass.PropertyClass Properties
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public void test()
{
Properties.zxc = 5;
}
}