So, first I have my command property interface
public interface ICommandProperty<T, U>
{
Func<T> CreateCommand { get; set; }
Func<T, U> ParseResponse { get; set; }
}
The idea is that I can create a simple parser that takes a string and returns an IPAddress for example.
This interface is then used in another interface:
public interface IDeviceCommand
{
Func<ICommandProperty<object, object>> SetCommand
{
get;
set;
}
Func<ICommandProperty<object, object>> GetCommand
{
get;
set;
}
string Name { get; set; }
}
I may be going about this all wrong, but this is where I have the problem. Currently I have the generic interface declared with objects because I can't figure out a way to set them generically(IDeviceCommand can't be generic for various reasons).
My concrete implementation looks like this:
public class DeviceCommand:IDeviceCommand
{
public DeviceCommand(string name,Func<ICommandProperty<object,object>> Set,Func<ICommandProperty<object,object>> Get)
{
this.Name = name;
this.SetCommand = Set;
this.GetCommand = Get;
}
#region IDeviceCommand Members
public string Name
{
get;
set;
}
public object Value
{
get;
set;
}
public Func<ICommandProperty<object, object>> SetCommand
{
get;
set;
}
public Func<ICommandProperty<object, object>> GetCommand
{
get;
set;
}
#endregion
}
I could make DeviceCommand be a generic class, and use T,U on the SetCommand and GetCommand, but then it doesn't satisfy the IDeviceCommand interface because Func<ICommandProperty<T,U>> isn't Func<ICommandProperty<object,object>>
Is there a different approach that I should be using here. In essence I'm trying to create a method pointer that I can set when I instantiate DeviceCommand.
Your questions seems a little vague, but here's some ideas. The first is to consider using methods instead of properties so that they can be generic rather than the class. Not sure if that will work for you. You could also consider passing a "builder" object into your Device command rather than the func<>'s themselves. Lastly, this gets hairy with your client knowing what to ask for and ensuring it is working with an object that has the correct func<> available. In that case, maybe something like the IDeviceCommand.Create and .Parse methods could work for you.
Lastly, if you are always looking for something to take a string and return an IP, the generics may not be necessary. Even plain old delegates could be explored.
public interface ICommandProperty<T, U>
{
Func<T> CreateCommand { get; set; }
Func<T, U> ParseResponse { get; set; }
}
public interface IDeviceCommand
{
void SetCreateCommand<T, U>(Func<ICommandProperty<T, U>> cmd);
void SetParseCommand<T, U>(Func<ICommandProperty<T, U>> cmd);
Func<ICommandProperty<T, U>> GetCreateCommand<T, U>();
Func<ICommandProperty<T, U>> GetParseCommand<T, U>();
void Create(object someKnownObject);
T Parse<T>(object someKnownObject);
string Name { get; set; }
}
public class DeviceCommand : IDeviceCommand
{
public DeviceCommand(IDeviceCommandBuilder builder)
{
builder.SetCommands(this);
}
public void SetCreateCommand<T, U>(Func<ICommandProperty<T, U>> cmd)
{
throw new NotImplementedException();
}
public void SetParseCommand<T, U>(Func<ICommandProperty<T, U>> cmd)
{
throw new NotImplementedException();
}
public Func<ICommandProperty<T, U>> GetCreateCommand<T, U>()
{
throw new NotImplementedException();
}
public Func<ICommandProperty<T, U>> GetParseCommand<T, U>()
{
throw new NotImplementedException();
}
public void Create(object someKnownObject)
{
throw new NotImplementedException();
}
public T Parse<T>(object someKnownObject)
{
throw new NotImplementedException();
}
public string Name
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
}
public interface IDeviceCommandBuilder
{
void SetCommands(IDeviceCommand command);
}
public class DeviceCommandBuilder : IDeviceCommandBuilder
{
public void SetCommands(IDeviceCommand command)
{
command.SetCreateCommand<string,Uri>(.)
;
command.SetParseCommand(.);
}
}
Related
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();
}
}
I have the following classes (omitted properties for sake of simplicity):
public class Person {
public Address Address { get; set; }
public Hobby Hobby { get; set; }
}
public class Address {
public Country Country { get; set; }
}
public class Country { }
public class Hobby { }
And I created an IncludeMapper to be used, if possible, as follows:
IncludeMapper<Person> m = IncludeMapper
.For<Person>()
.Add(person => person.Address).And(address => address.Country)
.Add(person => person.Hobby);
Add will take the base type, e.g, Person.
And will take the type used in the previous Add or And.
public class IncludeMapper {
public static IncludeMapper<T> For<T>() {
return new IncludeMapper<T>();
}
}
public class IncludeMapper<T> {
public IncludeMapper<T> Add<K>(String expression, Expression<Func<T, K>> property) {
return this;
}
public IncludeMapper<K> And<K>(String expression, Expression<Func<T, K>> property) {
return this;
}
}
This won't work ... I think I need to return on the methods and I might need an extra class because the For is only for T?
Could someone help me out with this?
I want to create an object that implements an interface and t hen return a reference to it. I've seen how to test whether the object implements an interface but I'm not sure how to do it in the first place.
The interface is as follows:
public interface IInformation
{
string name { get; set; }
string description { get; }
string age { get; set; }
}
And this is where I am trying to create the object, in a new class:
public IInformation NewInformation(string description)
{
}
Any help would be appreciated!
To implement a interface you need to create a class say 'myClass' in my example and use the ':' symbol followed by the interface name. then right click the interface and press the button 'implement interface' this will auto generate all of the methods of your interface but you need to make sure that you change the default implementation from
throw new NotImplementedException();
to whatever logic you wish to use.
public interface IInformation
{
string name { get; set; }
string description { get; }
string age { get; set; }
}
public class myClass : IInformation
{
public string age
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public string description
{
get
{
throw new NotImplementedException();
}
}
public string name
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
}
Then to use the class you will need to do something like this:
public IInformation NewInformation(string description)
{
myClass myInstance = new myClass();
myInstance.description = description;
return myInstance;
}
I have an interface
public interface IImageFilter<TIn, TOut>
{
// Properties
TIn Input { get; set; }
string Name { get; set; }
Guid Guid { get; set; }
TOut Process(TIn frame);
}
and I needed an observable collection of objects that implement the interface.
private ObservableCollection<IImageFilter<T, U>> _imageFilters;
the object that i pass to the collection can be
IImageFilter<string, string>
IImageFilter<string, int>
IImageFilter<int, double>
How do it declare the _imageFilters? what's the T? or U?
Closes you can get to it is
private ObservableCollection<object> _imageFilters;
If you have control over the IImageFilter, you can do something like:
public interface IImageFilterBase {
object Input { get; set; }
string Name { get; set; }
Guid Guid { get; set; }
object Process(object frame);
}
public interface IImageFilter<TIn, TOut> : IImageFilterBase {
// Properties
new TIn Input { get; set; }
TOut Process(TIn frame);
}
public abstract class FilterBase<TIn, TOut> : IImageFilter<TIn, TOut> {
public TIn Input { get; set; }
public abstract TOut Process(TIn frame);
object IImageFilterBase.Input {
get { return this.Input; }
set { this.Input = (TIn)value; }
}
public string Name { get;set;}
public Guid Guid { get; set; }
public object Process(object frame) {
return this.Process((TIn)frame);
}
}
// test class
public class StringToInt32 : FilterBase<string, int> {
public override int Process(string frame) {
return Convert.ToInt32(frame);
}
}
and declare the collection like
private ObservableCollection<IImageFilterBase> _imageFilters;
Not really impossible, Another approach is to use Covariant Generic type. But it will require some change in your interface.
Your Interface:
internal interface IImageFilter<out I, out O>
{
I Input { get; }
O Process();
}
Interface Implementation
public class ImageFilter : IImageFilter<string, string>
{
public string Input { get; private set; }
public ImageFilter(string input)
{
Input = input;
}
public string Process()
{
return Input.ToUpper();
}
}
Usage:
List<IImageFilter<object, object>> filters= new List<IImageFilter<object, object>>();
ImageFilter filter= new ImageFilter("something");
filters.Add(filter);
The designs of generic interfaces within the Framework, as well as the design of delegates (which provided quasi-generic behavior before real generics were available), require that all generic type parameters be replaced with closed-form generics. It is possible to design interfaces for use with open-form generics, but the interfaces within the framework are not suitable.
As a simple example, suppose one wishes to have an interface which is somewhat analogous to Action<T>, but instead of taking a parameter of type T, it will accept one parameter of any type which satisfies two constraints, TC1 and TC2. One could define it as:
interface ActStatisfyingConstraints<in TC1, in TC2>
{
void Invoke<T>(ref T param) where T:TC1,TC2;
}
Note that an implementation of that interface would be able to pass a T as a generic parameter to any other method which constrained it to TC1 and TC2, even if there is no single class which satisfies both constraints and also serves as a base class for all objects that do.
In the case of your observable collection, you should define an observer interface which includes notification methods like those above. The event-subscribe method would keep a list of references to the observers; adding something to the collection should then call the generic notify-of-added-item method on the each item in the list.
I'm quite new to C# and currently developing an application using the EntityFramework. I would like to extend the functionality of the database context class, so that I can call a method getPool() so that it hands out the according DbSet member of the class.
I need to implement it as a template as it will be later called from other templates, which are just knowing about the (global) database context object and a type T (having a given superclass) for which they shall query the database.
Here is what I tried (a bit simplified - original example is too complicated):
public class TestContext : DbContext
{
public DbSet<TestA> ATests { get; set; }
public DbSet<TestB> BTests { get; set; }
public IQueryable<T> getPool<T>() where T : TestA {
return (IQueryable<T>)ATests;
}
public IQueryable<T> getPool<T>() where T : TestB {
return (IQueryable<T>)BTests;
}
}
The error message is
Error: Type '...' already defines a member called '...' with the same parameter types.
And it occurs at the line of the second specialized definition of my template (public IQueryable<T> getPool<T>() where T : TestB).
The question is: How to fix this?
Unfortunately, in C#, you cannot overload a method by using a generic type constraint like this. You will have to give them different names like this
public class TestContext : DbContext
{
public DbSet<TestA> ATests { get; set; }
public DbSet<TestB> BTests { get; set; }
public IQueryable<T> getPoolA<T>() where T : TestA {
return (IQueryable<T>)ATests;
}
public IQueryable<T> getPoolB<T>() where T : TestB {
return (IQueryable<T>)BTests;
}
}
Another solution would be to do something like this:
public class TestContext : DbContext
{
public DbSet<TestA> ATests { get; set; }
public DbSet<TestB> BTests { get; set; }
public IQueryable<T> getPool<T>() {
return (typeof(T) == typeof(TestA))
? (IQueryable<T>)ATests
: (IQueryable<T>)BTests;
}
}
Now, you can make this even cleaner, since IQueryable<T> is covariant in T, you can avoid casting:
public class TestContext : DbContext
{
public DbSet<TestA> ATests { get; set; }
public DbSet<TestB> BTests { get; set; }
public IQueryable<T> getPool<T>() {
return (typeof(T) == typeof(TestA)) ? ATests : BTests;
}
}
If you want to avoid testing for types you can do something like this:
public class TestContext : DbContext
{
readonly Dictionary<Type, object> _sets;
public DbSet<TestA> ATests { get; set; }
public DbSet<TestB> BTests { get; set; }
public TestContext()
{
_sets = new Dictionary<Type, object>
{
{ typeof(TestA), ATests },
{ typeof(TestB), BTests }
}
}
public IQueryable<T> getPool<T>() {
return (IQueryable<T>)_sets[typeof(T)];
}
}
I'd recommend (besides of reading about generics and C# in general) to configure the pool with desired types on run time, store them in dictionaries and use the Type as key, i.e. something along the following lines...:
//...
// configuration, maybe factor out to a dedicated class...
private readonly IDictionary<System.Type, IQueryable> m_SupportedPools =
new Dictionary<System.Type, IQueryable>();
// add this queryable, note that type inference works here
public void AddToPool<T>(IQueryable<T> p_Queryable)
{
m_SupportedPools.Add(typeof(T), p_Queryable);
}
public IQueryable<T> GetPool<T>()
{
IQueryable t_Set = null;
if (m_SupportedQueries.TryGetValue(typeof(T), out t_Set)) {
return t_Set as IQueryable<T>;
} else {
return null;
}
}