Let's say I have an interface:
interface IPerson
{
int Age { get; set; }
string Name { get; set; }
bool Alive { get; set; }
}
and a Class:
public class Person : IPerson
{
public int Age { get; set; }
public string Name { get; set; }
}
That would not compile since Person does not implement the Alive Property.
What I would like to know is if there is a way to have the same behaviour, if Person adds an extra property that is not found in its interface.
interface IPerson
{
int Age { get; set; }
string Name { get; set; }
}
and a Class:
public class Person : IPerson
{
public int Age { get; set; }
public string Name { get; set; }
public bool Alive { get; set; } <---- This should prevent it from compiling as well.
}
I would want it to not compile as well, or at the very least give me a compile warning.
No. Interfaces define what members an object must implement. They cannot define members that an object can't implement. You could potentially use your own custom, or third party code analysis tools, to identify cases like this, but there is nothing in the language itself that would support it.
No it is not possible. Are you not trying to define a class itself here? Why do you really need an interface?
However, what you can achieve is make calls to your interface and not your class by doing
IPerson person = new Person();
this way you limit the person object to access only the methods defined in your interface.
There is a way to do this, but not within the object and its a bit silly to use in construction of the object. Using Reflection, you can check the type of an instance of your object and iterate through its properties, throwing an exception if the count or names of properties do not match your desired instance. Please note that if you just check against the interface, implementing objects will pass, so you would check against the desired concrete type. I am on my phone or I'd add some sample code, will try to return to this later.
There is a way to do this, but not within the object and its a bit silly to use in construction of the object. Using Reflection, you can check the type of an instance of your object and iterate through its properties, throwing an exception if the count or names of properties do not match your desired instance. Please note that if you just check against the interface, implementing objects will pass, so you would check against the desired concrete type. I'm on my phone so no sample code. Will try to return to this later.
Related
I have a class Thing that is deserialized from a JSON file using DataContractJsonSerializer:
[DataContract]
class Thing
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
// and so on...
}
To make this work, all properties need to have public or at least internal setters.
Two other modules (assemblies) need to access this class:
ThingView should have read-only access to most attributes.
ThingEditor needs full access to all attributes.
I could make the setters internal but then the ThingEditor would not get full access.
To restrict access for the ThingView class, the best idea I could come up with is to create a read-only wrapper of the Thing class. But this would involve a lot of code duplication.
Are there better ways to achieve more encapsulation for in a case like this?
(The actual code contains about 20 classes of this type, some of which form nested structures. Also, there are more than two modules that need either read or full access to the properties.)
There is nothing out of the box in the specs that would achieve this. However, you could do something like this for example
public interface IReadOnlInterface
{
int Id { get; }
string Name { get; }
}
public interface IInterface
{
int Id { get; set; }
string Name { get; set; }
}
internal class Thing : IInterface , IReadOnlInterface
{
public int Id { get; set; }
public string Name { get; set; }
}
However there is nothing stopping coders with dirty little fingers casting to the other interface. If its only a runtime issue, then interfaces should be fine. Otherwise youll have to create a better api design with secured data, and proxy type objects with readonly access, Though maybe someone has a better idea.
I have a instance method that creates a new instance of a class. I would like for this to be a class method. The problem is that I get an error when trying to call GetType() in the static method. Is it possible to convert this method to a static method ?
error
An object reference is required for the non-static field, method or property 'object.GetType()'.
Customer.New
public object WithAttributes(ExpandoObject valueObject)
{
var properties = GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.GetSetMethod() != null);
var self = Activator.CreateInstance(GetType());
var values = (IDictionary<string, object>)valueObject;
foreach (var property in properties)
{
if (values.Keys.Contains(property.Name))
{
var val = values[property.Name];
property.SetValue(self, values[property.Name]);
}
}
return self;
}
BaseEntity.cs
public class BaseEntity
{
public Int64 Id { get; set; }
public DateTime AddedDate { get; set; }
public DateTime ModifiedDate { get; set; }
public string IPAddress { get; set; }
public object WithAttributes(ExpandoObject valueObject)
{
// Same code as above
}
}
Customer.cs
public class Customer : BaseEntity
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string MobileNo { get; set; }
}
Desired Usage
dynamic attributes = new ExpandoObject();
attributes.FirstName = "James";
attributes.LastName = "Jones";
var customer = Customer.WithAttributes(attributes);
Well, Unfortunately for you it is impossible to get the implementing type from the base abstract type's static method. According to reed copsey's answer here and to Jon Skeet's answer there. As you can see in Jon's answer, the c# compiler associate the static method to the type it was declared in, even if it was executed from a deriving type.
This means that your abstract class must be aware of the type that implements it, or at least this method must be aware of the type where it's called from.
One way to do it is to create the WithAttributes as a generic method:
public static T WithAttributes<T>((ExpandoObject valueObject)) where T: BaseEntity, new
{
// Here you can use typeOf(T)
}
This have some advantages (for instance, you can simply write var self = new T() instead of using Activator.CreateInstance(), and you don't need to return an object but the actual type.
However, you can't force the code that's calling this method to pass the correct type - nothing is stopping you from doing something like this:
var customer = Customer.WithAttributes<SomeOtherBaseEntityDerivedClass>(attributes);
Rob Leclerc's answer here Is another attempt to solve this using generics, Only this is creating the entire abstract class as a generic class, so instead of public class BaseEntity you will have
public class BaseEntity<TChild>
and then you can use typeOf(TChild).
This has the same disadvantage as my suggestion (you can do public class Customer : BaseEntity<SomeOtherType> just as easily).
Daniel A. White Answered his own question by taking the type as a parameter to the static method in the abstract class:
public static object WithAttributes(Type type, ExpandoObject valueObject)
Again, it has the same drawbacks as using the generic approach, but it also have the drawbacks of your approach - it must return object and you must use Activator.CreateInstance.
To conclude - What you are asking for can't be done safely.
I will not recommend using any of these approaches for a public API, but If you know your team are the only programmers that will inherit the BaseEntity, I would probably go with the generic approach, as long as you make sure everybody knows the compiler can't protect them from using the wrong type parameter.
is there any diffrence between this 3 auto properties ?
interface MyInterface {
public int p1 { get; set; }
public int p2 { get; }
public int p3 { set; }
}
also why we can write this code in an interface but not in a class ?
public int p { get; }
For the same reason you can write this in an interface:
interface IFace {
void Test();
}
Also, your interface is invalid, as public isn't valid in an interface. The point being, different things are legal in interfaces and classes.
When you do public int P1 { get; set; } in a class, that turns into a auto property. However, you can't do public int P1 { get; }, because what would you want that to mean? Should it always return 0? There is no way to set it. So if you want a read only property you have to define the getter yourself like this:
int _p1;
public int P1 {
get { return _p1; }
}
Also. Another way to achieve more or less the same is this:
public int P1 { get; private set; }
There are differences between those properties. Firstly, you should remove the public modifier from your declaration. Secondly, by putting get or set within the block you define what properties in derived classes should look like. For example, public int p1 { get; set; } requires getter and setter in a derived class, public int p2 { get; } only getter, and public int p3 { set; } requires only setter to be implemented.
You can't use access modifiers inside interfaces because interfaces are guidelines for other developers that force them to go in a certain direction when developing the implementing classes.
Look at this post for more information about that.
Keep in mind interface does NOT contain any implementation data. When you add property in an interface, it merely says that a class implementing this interface needs to have said property with get, set or both methods, depending on what you wrote. So any class implementing your interface has to implement (or have auto-generated) p1 property with get and set method, p2 with get method, and p3 with set method. Interface doesn't care whether these will be auto-generated or your own custom implementations, they just have to be in an implementing class.
Therefore, you can write
int p { get; }
in an interface as all it does is telling that any class implementing this interface has to have property p with getter, again, not caring about its actual implementation - you could write a getter that does some computations, returns some constant, etc. OTOH in a class writing the same would mean that you want a property with auto-generated backing field, except since it would have no setter, you couldn't actually change its value, so it would always have its default value 0.
And as noted, you cannot write access modifiers in an interface, as all interface members are implicitly public.
When I define an interface that contains a write-only property:
public interface IModuleScreenData
{
string Name { set; }
}
and attempt to (naively) implement it explicitly with an intention for the property to also have a publicly available getter:
public class ModuleScreen : IModuleScreenData
{
string IModuleScreenData.Name { get; set; }
}
then I get the following error:
Error 'IModuleScreenData.Name.get' adds an accessor not found in
interface member 'IModuleScreenData.Name'
The error is more or less expected, however, after this alternative syntax:
public class ModuleScreen : IModuleScreenData
{
public string Name { get; IModuleScreenData.set; }
}
has failed to compile, I suppose that what I am trying to do is not really possible. Am I right, or is there some secret sauce syntax after all?
You can do this:
public class ModuleScreen : IModuleScreenData
{
string IModuleScreenData.Name
{
set { Name = value; }
}
public string Name { get; private set; }
}
On a side note, I generally wouldn't recommend set-only properties. A method may work better to express the intention.
You can't change the how the interface is implemented in the inheriting class. That is the whole point.. if you need to do something new with a property you could make a new property that references the inherited properties specific implementation. Interfaces are there so you can conform to a specified standard for object inheritance.
UPDATE:
On second thought.. you should be able to just do this.... this will compile fine:
public class ModuleScreen : IModuleScreenData
{
public string Name { get; set; }
}
This might be a simple one, but my head is refusing to wrap around that, so an outside view is always useful in that case!
I need to design an object hierarchy to implement a Parameter Registration for a patient. This will take place on a certain date and collect a number of different parameters about a patient (bloodpressure, heartrate etc). The values of those Parameter Registrations can be of different types, such as strings, integers, floats or even guids (for lookup lists).
So we have:
public class ParameterRegistration
{
public DateTime RegistrationDate { get; set; }
public IList<ParameterRegistrationValue> ParameterRegistrationValues { get; set; }
}
public class ParameterRegistrationValue
{
public Parameter Parameter { get; set; }
public RegistrationValue RegistrationValue { get; set; } // this needs to accomodate the different possible types of registrations!
}
public class Parameter
{
// some general information about Parameters
}
public class RegistrationValue<T>
{
public RegistrationValue(T value)
{
Value = value;
}
public T Value { get; private set; }
}
UPDATE: Thanks to the suggestions, the model has now morphed to the following:
public class ParameterRegistration
{
public DateTime RegistrationDate { get; set; }
public IList<ParameterRegistrationValue> ParameterRegistrationValues { get; set; }
}
public abstract class ParameterRegistrationValue()
{
public static ParameterRegistrationValue CreateParameterRegistrationValue(ParameterType type)
{
switch(type)
{
case ParameterType.Integer:
return new ParameterRegistrationValue<Int32>();
case ParameterType.String:
return new ParameterRegistrationValue<String>();
case ParameterType.Guid:
return new ParameterRegistrationValue<Guid>();
default: throw new ArgumentOutOfRangeException("Invalid ParameterType: " + type);
}
}
public Parameter Parameter { get; set; }
}
public class ParameterRegistrationValue<T> : ParameterRegistrationValue
{
public T RegistrationValue {get; set; }
}
public enum ParameterType
{
Integer,
Guid,
String
}
public class Parameter
{
public string ParameterName { get; set; }
public ParameterType ParameterType { get; set;}
}
which is indeed a bit simpler, but now I'm wondering, since the IList in ParameterRegistration points to the abstract ParameterRegistrationValue object, how will I be able to get the actual value out (since its stored on the sub-objects)?
Maybe the whole generic thing is indeed not quite the way to go after all :s
If you don't know the final set of parameter and the corresponding type of each parameter then the generics probably won't help - use object as a parameter value type.
Furthermore iterating through the list of parameters will be a pain since you'll have to examine the type of each item in order to determine how to treat the value.
What are you trying to achieve with generics ? Yes, they are cool (and going for boxing/unboxing is probably not a best idea), but in some cases you might want to use object instead (for both simplicity and flexibility).
-- Pavel
What you might want to introduce is an abstract base class for RegistrationValue<T> that is not generic, so that your ParameterRegistrationValue class can hold a non-generic reference, without needing knowledge of the type involved. Alternatively, it may be appropriate to make ParameterRegistrationValue generic also, and then add a non-generic base class for it instead (so that the list of values in ParameterRegistration can be of different types.
1st way:
public abstract class RegistrationValue
{
}
public class RegistrationValue<T> : RegistrationValue
{
public RegistrationValue(T value)
{
Value = value;
}
public T Value { get; private set; }
}
And now your code should compile.
Once you have a non-generic base class, I'd also move any members of the generic class that don't depend on the generic type parameters up into this base class. There aren't any in this example, but if we were instead modifying ParameterRegistrationValue to be generic, I'd move Parameter up into the non-generic base class (because it doesn't depend on the type parameter for RegistrationValue)
May be, you should use public RegistrationValue RegistrationValue, where T - is type, using in generic. For example, T - is String or other class or struct.
Or you should make class ParameterRegistrationValue as generic, to use generic argument in the field RegistrationValue.
I believe you want to have a collection of instances of different RegistrationValues-derived classes and be able to iterate it and for to have different type for each element. That's rather impossible.
You'll still need to cast each element to the type you know it is, because iterating the collection will return references to your base type (ParameterRegistrationValue - this one specified by IList type parameter). So it won't make any real difference from iterating over non-generic object list.
And if you can safely do that casting for each parameter (you know all the types), you probably don't need collection like this at all - it'll be better to have a class that encapsulates all the parameters in one type, so that you can call it with strong types, with IntelliSense etc. like this:
public class ParameterRegistration
{
public DateTime RegistrationDate { get; set; }
public PatientData PatientData { get; set; }
public Guid Identifier { get; set; }
// ...
}