What i want to achieve is simple, i have an Interface IDatasource, which has a property called DatasourceSettings
public interface IDatasource
{
DatasourceSettings DatasourceSettings { get; set; }
}
The implementing Class looks like this
public class TestDatasource : IDatasource
{
public DatasourceSettings IDatasource.DatasourceSettings { get { return DatasourceSettings; } set { DatasourceSettings = (TestDatasourceSettings)value; } }
public TestDatasourceSettings DatasourceSettings { get; set; }
}
As you may possibly see, the property is first implemented explicit, and it should return the DatasourceSettings Property of the class itself
So on, here is what i want to achieve
var ds = new TestDatasource();
if (ds.DatasourceSettings is TestDatasourceSettings &&
((IDatasource)ds).DatasourceSettings is DatasourceSettings)
{
// should be true
}
The Error i get :
The modifier 'public' is not valid for this item
So What's wrong here?
Remove the public from
public DatasourceSettings IDatasource.DatasourceSettings
Because it is explicitly implementing an interface method it is a-priori public
public class TestDatasource : IDatasource
{
DatasourceSettings IDatasource.DatasourceSettings { get { return DatasourceSettings; } set { DatasourceSettings = (TestDatasourceSettings)value; } }
public TestDatasourceSettings DatasourceSettings { get; set; }
}
Had the same mistake recently... turns out if the implementation is explicit you don't write access modifier.
Related
I want to create an interface which can handle multiple other object of one interface.
I tried using the interface in the interface and using an object in the new class.
public interface IObject
{
double Value { get; set; }
}
public class FirstObject: IObject
{
double Value { get; set; }
}
public class SecondObject: IObject
{
string Titel { get; set; }
double Value { get; set; }
}
public interface ICollection
{
IObject[] Values { get; set; }
}
public class Collection: ICollection
{
SecondObject[] Values { get; set; }
}
Now I get the error, that my Collection doesn't implement the IObject[] Values member.
I thought when I use an object (SecondObject) which is implementing from the interface IObject the Collection should handle this.
What am I doing wrong and how can I solve this?
You might be off better here using generics:
public interface ICollection<T> where T : IObject
{
T[] Values { get; set; }
}
public class Collection : ICollection<SecondObject>
{
public SecondObject[] Values { get; set; }
}
The reason that it doesn't work now, is that the signature should match exactly. That means the Values should be an array of IObject, which it isn't. Using generics you can solve this, while keeping the type constraint.
A second, but inadvisable solution would be using an explicit interface implementation:
public SecondObject[] Values { get; set; }
IObject[] ICollection.Values
{
get
{
return this.Values;
}
set
{
this.Values = value?.Cast<SecondObject>().ToArray();
}
}
Original Question
So I have this 3 objects...
public class obj1
{
public int Id { get; set; }
public string Name { get; set; }
}
public class obj2
{
public int AccNum { get; set; }
public string Name { get; set; }
}
public class obj3
{
public string Email { get; set; }
public string Phone { get; set; }
}
... and one method that is supposed to receive one of them, after evaluating the object type the program should decide which function to call.
I've tried with generics but it doesn't work as I expected. So far this is what I've got...
public class NotificationHelper: INotificationHelper
{
public bool SendNotification<TNotInfo>(TNotInfo obj) where TNotInfo : class
{
if (contract.GetType() == typeof (obj1))
{
var sender = new SendSMS();
return sender.Send(obj);
}
if (contract.GetType() == typeof(obj2))
{
var sender = new SendPush();
return sender.Send(obj);
}
else
{
var sender = new SendEmail();
return sender.Send(obj);
}
}
}
but I get the error "Cannot convert from TNotInfo to Models.obj1". Is there any way to overcome this issue? Or I have to change my logic?
Appreciate any help, thanks in advance.
*Edit
using System;
namespace EmailNotifications
{
public interface IEmailNotification
{
void SendEmailNotification();
}
public class EmailNotificationA : IEmailNotification
{
public void SendEmailNotification(Contract1 a)
{
Console.WriteLine($"Sending EmailNotificationA ({a})");
}
}
public class EmailNotificationB : IEmailNotification
{
public void SendEmailNotification(Contract2 b)
{
Console.WriteLine($"Sending EmailNotificationB ({b})");
}
}
public class EmailNotificationC : IEmailNotification
{
public void SendEmailNotification(Contrac3 c)
{
Console.WriteLine($"Sending EmailNotificationC ({c})");
}
}
public class EmailNotificationService
{
private readonly IEmailNotification _emailNotification;
public EmailNotificationService(IEmailNotification emailNotification)
{
this._emailNotification = emailNotification;
}
public void ServiceHelper()
{
_emailNotification.SendEmailNotification();
}
}
}
Above solution is what I was trying to achieve, applying strategy design pattern. But I couldn't manage to make my interface method receive different objects, this is required because each notification has is own implementation. As visible at the none working example above, I have 3 different implementation of the same method all of them receiving different objects. Any idea of how to make this logic work?
This is the kind of thing that interfaces were designed to do. First, define a common interface:
public interface INotifier
{
bool Notify();
}
Second, implement it in your objX classes:
public class obj1 : INotifier
{
public int Id { get; set; }
public string Name { get; set; }
public bool Notify()
{
var sender = new SendSMS();
return sender.Send(this);
}
}
public class obj2 : INotifier
{
public int AccNum { get; set; }
public string Name { get; set; }
public bool Notify()
{
var sender = new SendPush();
return sender.Send(this);
}
}
public class obj3 : INotifier
{
public string Email { get; set; }
public string Phone { get; set; }
public bool Notify()
{
var sender = new SendEmail();
return sender.Send(this);
}
}
And finally, change your notification method to accept the interface type as the parameter:
public class NotificationHelper : INotificationHelper
{
public bool SendNotification(INotifier obj)
{
return obj.Notify();
}
}
Edit (2019):
I'm revisiting this answer as it seems to be getting a fair amount of visibility. OP has probably long since moved on, but for others that may stumble upon this answer, here's another solution.
I still believe that interfaces are the way to go. However, the interface suggested above is extremely generic and ultimately not terribly useful. It also runs into some DRY violations because, as Fabio said in a comment, if two objX classes implement notifications in the same way, this approach forces you to duplicate the code between them.
Instead of one global interface, instead have interfaces for each specific notification task, i.e. ISMSNotification, IPushNotification, IEmailNotification. You can then use the mixin pattern to give each interface instance a default implementation of the send method:
interface ISmsNotifier
{
int SmsId { get; }
string SmsName { get; }
}
static class ISmsNotifierExtensions
{
public static bool NotifySms(this ISmsNotifier obj)
{
var sender = new SendSMS();
return sender.Send(obj);
}
}
// ---------------------------------------------
interface IPushNotifier
{
int PushAccNum { get; }
string PushName { get; }
}
static class IPushNotifierExtensions
{
public static bool NotifyPush(this IPushNotifier obj)
{
var sender = new SendEmail();
return sender.Send(obj);
}
}
// ---------------------------------------------
interface IEmailNotifier
{
string EmailAddress { get; }
string EmailPhone { get; }
}
static class IEmailNotifierExtensions
{
public static bool NotifyEmail(this IEmailNotifier obj)
{
var sender = new SendEmail();
return sender.Send(obj);
}
}
You can then implement it in the objX classes like so:
public class obj1 : INotifier, ISmsNotifier
{
public int SmsId { get; set; }
public string SmsName { get; set; }
public bool Notify() => this.NotifySms();
}
public class obj2 : INotifier, IPushNotifier
{
public int PushAccNum { get; set; }
public string PushName { get; set; }
public bool Notify() => this.NotifyPush();
}
public class obj3 : INotifier, IEmailNotifier
{
public string EmailAddress { get; set; }
public string EmailPhone { get; set; }
public bool Notify() => this.NotifyEmail();
}
Notice that using this approach it's easy to not only support objects which use identical notification systems, you can also support objects with multiple notification systems:
public class obj4 : INotifier, IEmailNotifier, IPushNotifier
{
public int PushAccNum { get; set; }
public string PushName { get; set; }
public string EmailAddress { get; set; }
public string EmailPhone { get; set; }
public bool Notify() => this.NotifyEmail() && this.NotifyPush();
}
You might notice that this approach makes NotificationHelper obsolete since it's no longer necessary to pass the objects through a processing step to determine which notification system to process the object through. That is true, and maybe rightfully so, since the objects should be fully capable of deciding that for themselves (depending on your mentality approaching this problem). However, NotificationHelper may still have its uses, such as if you wanted to preprocess the information that's getting sent to the notification services, or if you wanted a common point of entry to help with mocking and testing.
C# 8 Note:
A proposed feature of C# 8 is the ability to give interfaces a default implementation of methods within the interface definition itself. When (if) that happens, you don't need to use the mixin pattern anymore and can directly define the default method implementations in the interfaces. The feature hasn't yet been finalized, but it might look something like this:
interface ISmsNotifier
{
int SmsId { get; }
string SmsName { get; }
public bool NotifySms()
{
var sender = new SendSMS();
return sender.Send(this);
}
}
// ---------------------------------------------
interface IPushNotifier
{
int PushAccNum { get; }
string PushName { get; }
public bool NotifyPush()
{
var sender = new SendEmail();
return sender.Send(this);
}
}
// ---------------------------------------------
interface IEmailNotifier
{
string EmailAddress { get; }
string EmailPhone { get; }
public bool NotifyEmail()
{
var sender = new SendEmail();
return sender.Send(this);
}
}
Another approach will be overload methods.
Because you have different logic based on the given type. And types have nothing in common (interface/abstract class).
public class NotificationHelper
{
public bool SendNotification(obj1 obj)
{
var sender = new SendSMS();
return sender.Send(obj);
}
public bool SendNotification(obj2 obj)
{
var sender = new SendPush();
return sender.Send(obj);
}
public bool SendNotification(obj3 obj)
{
var sender = new SendEmail();
return sender.Send(obj);
}
}
Then using will be clear enough
var someObject = GetObjectFromSomeWhere();
var isSuccessful = SendNotification(someObject);
I would suggest creating a parent class from which these 3 inherit
public class ParentType { }
public class Obj1 : ParentType { ... }
The method would then just request the parent type, such as:
public bool SendNotification(ParentType obj) { ... }
I'm trying to cache some classes in a List.
Because this class has a generic Property, I created a none-generic Type of the class which is the Type of this List.
So my BOs looks like this:
public class Model<T> : Model where T : class
{
public T Cls
{
get { return (T) ClsObject; }
set { ClsObject = value; }
}
}
public class Model
{
public List<ModelProperty> Properties { get; set; }
public string ModelName { get; set; }
public Type ClsType { get; set; }
public object ClsObject { get; set; }
}
So here's the Caching-Class:
private static List<Model> CachedModels {get; set;}
public static Model<T> GetCachedVersion<T>(this T cls) where T : class
{
var ret = CachedModels.FirstOrDefault(x => x.ClsType == typeof(T));
return ret != null ? (Model<T>)ret : null;
}
But the casting from the GetCachedVersion-Method crashes and I don't understand why.
Thanks for any tips!
If you are looking for the first object of type Model<T> you could change your code to
public static Model<T> GetCachedVersion<T>(this T cls) where T : class
{
return CachedModels.OfType<T>.FirstOrDefault();
}
There are a number of things you might wish to consider. Because if things were as you expected them to be your code should work no different from this.
1) tie the ClsType to the ClsObject or T
2) remove the setter (or otherwise hide it from external code) of ClsObject since it violates the invariant of Cls. You can set the Cls property to something that's not a T
public class Model {
public List<ModelProperty> Properties { get; set; }
public string ModelName { get; set; }
public virtual Type ClsType { get {
ClsObject.GetType();
} }
public object ClsObject { get; protected set; }
}
public class Model<T> : Model {
public override Type ClsType { get{
return typeof(T);
}}
public T Cls
{
get { return (T) ClsObject; }
set { ClsObject = value; }
}
}
1st guesses:
Are you by any chance using a nullable type anywhere in your code like Model?
See if you are setting ClsType properly.
It looks like you would have to create a Helper-Class which created the generic Type through reflections. There's no other way to downcast besides hardcode it.
I would like to have this kind of design :
public interface IDifferentTypes
{
}
public class IntegerType : IDifferentTypes
{
public int value { get; set; }
}
public class StringType : IDifferentTypes
{
public string value { get; set; }
}
public class DateTimeType : IDifferentTypes
{
public DateTime value { get; set; }
}
but with the property 'value' defined in the interface.
So I can call something like that :
IDifferentTypes someInt = GetSomeInt(); // GetSomeInt() returns a IntegerType object
Assert.AreEqual(5, someInt.value);
IDifferentTypes someString = GetSomeString(); // GetSomeString() returns a StringType object
Assert.AreEqual("ok", someString.value);
Problem is that the type of value is different for each implementation, what is the best way to deal with that?
You could define a generic interface (but it will have to be a property, or, more strictly, it can't be a field):
public interface IHasValue<T> {
T Value { get; }
}
Where T is the type, a placeholder, if you will, and you can do:
public class HasStringValue : IHasValue<string> {
public string Value { get; private set; }
}
Use generics if you can:
var someInt = GetSomeInt();
Assert.AreEqual(5, someInt.Value);
var someString = GetSomeString();
Assert.AreEqual("ok", someString.Value);
// ...
public interface IDifferentTypes<T>
{
T Value { get; set; }
}
public class IntegerType : IDifferentTypes<int>
{
public int Value { get; set; }
}
public class StringType : IDifferentTypes<string>
{
public string Value { get; set; }
}
public class DateTimeType : IDifferentTypes<DateTime>
{
public DateTime Value { get; set; }
}
interface IDifferentTypes
{
Object Value { get; set; }
}
class StringType : IDifferentTypes
{
string _value;
public Object Value
{
get
{
return _value;
}
set
{
_value = value as string;
}
}
}
But this means that every time you use StringType.Value you're going to need to recast it. You may want to also expose a public accessor of the specific type. You also may want to add some protections against assigning the wrong type:
class StringType : IDifferentTypes
{
public String StringProperty { get; set; }
public Object Value
{
get
{
// works with any type that can auto cast to `Object`
return StringProperty;
}
set
{
// Optional
if( typeof(string) != value.GetType() )
{
throw new MyException();
}
// works for any nullable type
StringProperty = value as string;
// OR
// throws an exception if conversion fails
StringProperty = (string)value;
}
}
}
I have this classes and interfaces:
public class XContainer
{
public List<IXAttribute> Attributes { get; set; }
}
public interface IXAttribute
{
string Name { get; set; }
}
public interface IXAttribute<T> : IXAttribute
{
T Value { get; set; }
}
public class XAttribute<T> : IXAttribute<T>
{
public T Value { get; set; }
}
I need to iterate over XContainer.Attributes and get property Value but I need to cast IXAttribute to correct generic representation like XAttribute<string> or XAttribute<int> but I don't want to use if-else if-else statement to check it like if XContainerl.Attributes[0] is XAttribute<string> then cast...
Is here a better way to do it?
There is a better way to do it.
Assuming you want to keep the current overall design, you could alter your non-generic interface and implementation as follows:
public interface IXAttribute
{
string Name { get; set; }
object GetValue();
}
public class XAttribute<T> : IXAttribute<T>
{
public T Value { get; set; }
public object GetValue()
{
return Value;
}
}
Then your iterator would just access GetValue(), no casting needed.
That said, I think the design might not be the best for what you're doing.
You could also define a generic extension method
public static class XAttributeExtensions
{
public T GetValueOrDefault<T>(this IXAttribute attr)
{
var typedAttr = attr as IXAttribute<T>;
if (typedAttr == null) {
return default(T);
}
return typedAttr.Value;
}
}
Then you can call it with (assuming T is int)
int value = myAttr.GetValueOrDefault<int>();
The reason for implementing it as an extension method is that it will work with any implementation of the non generic interface IXAttribute.