How to use an interface property set by one class and get the same in another class? - interface

`I have two classes, Class A and Class B inherited from Interface IA which has a property int count with get and set. How do I set that property value in one class and use the same value in another class?
I might not have written complete code here its just a sample one here:
public interface IA
{
int count
{
get;
set;
}
}
public class A: Class X,IA
{
private int _count;
public int count
{
get => _count;
set =>_count = value;
}
this.Count= 1;
}
public class B: Class Y,IA
{
private int robot1AvailableQue;
private int _count;
public int count
{
get => _count;
set =>_count = value;
}
if (count == 1)
{
spaceAvailable= true;
}
}

Related

If a type satisfies the implementation of an interface should it 'implement' it?

I have this interface
public interface IWeighted {
int Weight { get; }
}
and this attribute
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
public class WeightAttribute : Attribute {
private readonly int m_Weight;
public int Weight => m_Weight;
public WeightAttribute(int weight = 1) {
m_Weight = weight;
}
}
Should WeightAttribute implement IWeighted as it exactly matches the contract declared within IWeighted, or should it not seeing as WeightAttribute is an attribute (intended for use on enum members alone) and as such should not be target to selection itself?

Deserialize the immutable class with the custom constructor

I have a public class with some public immutable properties (only get;). It also has a custom constructor, which takes one additional parameter, required not for the setting of a property, but only for the calculations. I think, because of that, this class cannot be deserialized properly via Newtonsoft Json.
Other classes with only corresponding input parameters to the properties work fine.
So, this class deserializes itself not properly, returning zeros. It has additional parameter 'value' which is not related to any property, and just used for a calcualtions and presenting the data.
public class DurationData
{
public DateTime Start { get; }
public int Index { get; }
public double ActivityDurationInHours { get; }
public string Activetime { get; }
public ShiftDurationData(DateTime start, int index, TimeSpan value )
{
Start = start;
Index = shiftIndex;
ActivityDurationInHours = Math.Round(value.TotalHours, 1);
Activetime = $"{(int)value.TotalHours:d2}:{value.Minutes:D2}:{value.Seconds:D2}";
}
}
if I set the mock of this like below or just with mutable properties (get;set) and without a constructor it deserializes itself properly.
public class DurationData
{
public DateTime Start { get; }
public int Index { get; }
public double ActivityDurationInHours { get; }
public string Activetime { get; }
public ShiftDurationData(DateTime start, int index, double activityDurationInHours, string activeTime)
{
Start = start;
Index = shiftIndex;
ActivityDurationInHours = activityDurationInHours
ActiveTime = activetime ?? throw new ArgumentNullException(nameof(activeTime))
}
}
But I don't wan't to create additional mock class and would like to work with original. How to do this properly

How to get a property name of a given type strongly typed revisited?

How can I simplify the code below to avoid to pass the object for type inference on the generic method?
using System;
using System.Linq.Expressions;
namespace lambda
{
class Program
{
static void Main(string[] args)
{
var area = new Area { Name = "New Area" };
var propertyName = area.GetPropertyName(area, a => a.Name); // propertyName is COMPILE time checked
Console.WriteLine(propertyName);
}
}
public class Area
{
public int Id;
public string Name { get; set; }
}
public static class Extension
{
public static string GetPropertyName<T>(this Area entity, T e, Expression<Func<T, object>> path) // T e for type inference
{
var member = path.Body as MemberExpression;
if (member == null) throw new ArgumentException();
return member.Member.Name;
}
}
}
I mean instead of calling the extension method with area.GetPropertyName(area, a => a.Name)
just do a call like this area.GetPropertyName(a => a.Name), avoid to pass there area object just for type inference
I guess that I can’t do unless I refactor the signature of the method to GetPropertyName(this IEntity entity, Expression> path)
But in that case will be less obvius want I want at code writing time since I will need to specify the type on every call
I mean area.GetPropertyName( a => a.Name) seems to bel for me less clear writing code than writing area.GetPropertyName(area, a => a.Name)
The example code below works fine with asked requirements, no need to pass the object itself for type inference when calling the extension method
I used a base class and an interface that for my case works fine for all my domain class.
See code below
namespace UnitTestProject
{
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Linq.Expressions;
public interface IEntity<T>
{
}
public abstract class Entity<T> : IEntity<T> where T : class
{
}
public class Area : Entity<Area>
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime Created { get; set; }
public bool Closed { get; set; }
public string Description { get; set; }
}
public static class EntityExtension
{
public static string GetPropertyName<T>(this IEntity<T> entity, Expression<Func<T, object>> expr) // T e for type inference
{
var unary = expr.Body as UnaryExpression;
var member = expr.Body as MemberExpression;
return member != null ? member.Member.Name : (unary != null ? ((MemberExpression)unary.Operand).Member.Name : String.Empty);
}
}
[TestClass]
public class UnitTest
{
[TestMethod]
public void GetPropertyName_Tests()
{
var area = new Area();
var x = area.GetPropertyName(a => a.Id);
var y = area.GetPropertyName(a => a.Name);
var v = area.GetPropertyName(a => a.Created);
var w = area.GetPropertyName(a => a.Closed);
var z = area.GetPropertyName(a => a.Description);
Assert.AreEqual(x, "Id");
Assert.AreEqual(y, "Name");
Assert.AreEqual(v, "Created");
Assert.AreEqual(w, "Closed");
Assert.AreEqual(z, "Description");
}
}
}

Entity Framework options to map list of strings or list of int (List<string>)

I want to store an object that contains a List of primitives using EF.
public class MyObject {
public int Id {get;set;}
public virtual IList<int> Numbers {get;set;}
}
I know that EF cannot store this, but I'd like to know possible solutions to solve this problem.
The 2 Solutions I can think of are:
1.Create a Dummy object that has an Id and the Integervalue, e.g.
public class MyObject {
public int Id {get;set;}
public virtual IList<MyInt> Numbers {get;set;}
}
public class MyInt {
public int Id {get;set;}
public int Number {get;set;}
}
2.Store the list values as a blob, e.g.
public class MyObject {
public int Id {get;set;}
/// use NumbersValue to persist/load the list values
public string NumbersValue {get;set;}
[NotMapped]
public virtual IList<int> Numbers {
get {
return NumbersValue.split(',');
}
set {
NumbersValue = value.ToArray().Join(",");
}
}
}
The Problem with the 2. approach is, that I have to create a Custom IList implementation to keep track if someone modifies the returned collection.
Is there a better solution for this?
Although I do not like to answer my own question, but here is what solved my problem:
After I found this link about Complex Types I tried several implementations, and after some headache I ended up with this.
The List values get stored as a string on the table directly, so it's not required to perform several joins in order to get the list entries. Implementors only have to implement the conversation for each list entry to a persistable string (see the Code example).
Most of the code is handled in the Baseclass (PersistableScalarCollection). You only have to derive from it per datatype (int, string, etc) and implement the method to serialize/deserialize the value.
It's important to note, that you cannot use the the generic baseclass directly (when you remove the abstract). It seems that EF cannot work with that. You also have to make sure to annotate the derived class with the [ComplexType] attribute.
Also note that it seems not to be possible to implement a ComplexType for IList<T> because EF complains about the Indexer (therefore I went on with ICollection).
It's also important to note, that since everything is stored within one column, you cannot search for values in the Collection (at least on the database). In this case you may skip this implementation or denormalize the data for searching.
Example for a Collection of integers:
/// <summary>
/// ALlows persisting of a simple integer collection.
/// </summary>
[ComplexType]
public class PersistableIntCollection : PersistableScalarCollection<int> {
protected override int ConvertSingleValueToRuntime(string rawValue) {
return int.Parse(rawValue);
}
protected override string ConvertSingleValueToPersistable(int value) {
return value.ToString();
}
}
Usage example:
public class MyObject {
public int Id {get;set;}
public virtual PersistableIntCollection Numbers {get;set;}
}
This is the baseclass that handles the persistence aspect by storing the list entries within a string:
/// <summary>
/// Baseclass that allows persisting of scalar values as a collection (which is not supported by EF 4.3)
/// </summary>
/// <typeparam name="T">Type of the single collection entry that should be persisted.</typeparam>
[ComplexType]
public abstract class PersistableScalarCollection<T> : ICollection<T> {
// use a character that will not occur in the collection.
// this can be overriden using the given abstract methods (e.g. for list of strings).
const string DefaultValueSeperator = "|";
readonly string[] DefaultValueSeperators = new string[] { DefaultValueSeperator };
/// <summary>
/// The internal data container for the list data.
/// </summary>
private List<T> Data { get; set; }
public PersistableScalarCollection() {
Data = new List<T>();
}
/// <summary>
/// Implementors have to convert the given value raw value to the correct runtime-type.
/// </summary>
/// <param name="rawValue">the already seperated raw value from the database</param>
/// <returns></returns>
protected abstract T ConvertSingleValueToRuntime(string rawValue);
/// <summary>
/// Implementors should convert the given runtime value to a persistable form.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
protected abstract string ConvertSingleValueToPersistable(T value);
/// <summary>
/// Deriving classes can override the string that is used to seperate single values
/// </summary>
protected virtual string ValueSeperator {
get {
return DefaultValueSeperator;
}
}
/// <summary>
/// Deriving classes can override the string that is used to seperate single values
/// </summary>
protected virtual string[] ValueSeperators {
get {
return DefaultValueSeperators;
}
}
/// <summary>
/// DO NOT Modeify manually! This is only used to store/load the data.
/// </summary>
public string SerializedValue {
get {
var serializedValue = string.Join(ValueSeperator.ToString(),
Data.Select(x => ConvertSingleValueToPersistable(x))
.ToArray());
return serializedValue;
}
set {
Data.Clear();
if (string.IsNullOrEmpty(value)) {
return;
}
Data = new List<T>(value.Split(ValueSeperators, StringSplitOptions.None)
.Select(x => ConvertSingleValueToRuntime(x)));
}
}
#region ICollection<T> Members
public void Add(T item) {
Data.Add(item);
}
public void Clear() {
Data.Clear();
}
public bool Contains(T item) {
return Data.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex) {
Data.CopyTo(array, arrayIndex);
}
public int Count {
get { return Data.Count; }
}
public bool IsReadOnly {
get { return false; }
}
public bool Remove(T item) {
return Data.Remove(item);
}
#endregion
#region IEnumerable<T> Members
public IEnumerator<T> GetEnumerator() {
return Data.GetEnumerator();
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator() {
return Data.GetEnumerator();
}
#endregion
}
I'm using EF Core and had a similar problem but solved it in a simpler way.
The idea is to store the list of integers as a comma separated string in the database. I do that by specifying a ValueConverter in my entity type builder.
public class MyObjectBuilder : IEntityTypeConfiguration<MyObject>
{
public void Configure(EntityTypeBuilder<MyObject> builder)
{
var intArrayValueConverter = new ValueConverter<int[], string>(
i => string.Join(",", i),
s => string.IsNullOrWhiteSpace(s) ? new int[0] : s.Split(new[] { ',' }).Select(v => int.Parse(v)).ToArray());
builder.Property(x => x.Numbers).HasConversion(intArrayValueConverter);
}
}
More information can be found here: https://entityframeworkcore.com/knowledge-base/37370476/how-to-persist-a-list-of-strings-with-entity-framework-core-
Bernhard's answer is brilliant. I just couldn't help but refine it a little. Here's my two cents:
[ComplexType]
public abstract class EFPrimitiveCollection<T> : IList<T>
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public virtual int Id { get; set; }
const string DefaultValueSeperator = "|";
readonly string[] DefaultValueSeperators = new string[] { DefaultValueSeperator };
[NotMapped]
private List<T> _data;
[NotMapped]
private string _value;
[NotMapped]
private bool _loaded;
protected virtual string ValueSeparator => DefaultValueSeperator;
protected virtual string[] ValueSeperators => DefaultValueSeperators;
[ShadowColumn, MaxLength]
protected virtual string Value // Change this to public if you prefer not to use the ShadowColumnAttribute
{
get => _value;
set
{
_data.Clear();
_value = value;
if (string.IsNullOrWhiteSpace(_value))
return;
_data = _value.Split(ValueSeperators, StringSplitOptions.None)
.Select(x => ConvertFromString(x)).ToList();
if (!_loaded) _loaded = true;
}
}
public EFPrimitiveCollection()
{
_data = new List<T>();
}
void UpdateValue()
{
_value = string.Join(ValueSeparator.ToString(),
_data.Select(x => ConvertToString(x))
.ToArray());
}
public abstract T ConvertFromString(string value);
public abstract string ConvertToString(T value);
#region IList Implementation
public int Count
{
get
{
EnsureData();
return _data.Count;
}
}
public T this[int index]
{
get
{
EnsureData();
return _data[index];
}
set
{
EnsureData();
_data[index] = value;
}
}
public bool IsReadOnly => false;
void EnsureData()
{
if (_loaded)
return;
if (string.IsNullOrWhiteSpace(_value))
return;
if (_data.Count > 0) return;
if (!_loaded) _loaded = true;
_data = _value.Split(ValueSeperators, StringSplitOptions.None)
.Select(x => ConvertFromString(x)).ToList();
}
public void Add(T item)
{
EnsureData();
_data.Add(item);
UpdateValue();
}
public bool Remove(T item)
{
EnsureData();
bool res = _data.Remove(item);
UpdateValue();
return res;
}
public void Clear()
{
_data.Clear();
UpdateValue();
}
public bool Contains(T item)
{
EnsureData();
return _data.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
EnsureData();
_data.CopyTo(array, arrayIndex);
}
public int IndexOf(T item)
{
EnsureData();
return _data.IndexOf(item);
}
public void Insert(int index, T item)
{
EnsureData();
_data.Insert(index, item);
UpdateValue();
}
public void RemoveAt(int index)
{
EnsureData();
_data.RemoveAt(index);
UpdateValue();
}
public void AddRange(IEnumerable<T> collection)
{
EnsureData();
_data.AddRange(collection);
UpdateValue();
}
public IEnumerator<T> GetEnumerator()
{
EnsureData();
return _data.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
EnsureData();
return _data.GetEnumerator();
}
#endregion
}
With that base class you can have as many derivations as you like:
[ComplexType]
public class EFIntCollection : EFPrimitiveCollection<int>
{
public override int ConvertFromString(string value) => int.Parse(value);
public override string ConvertToString(int value) => value.ToString();
}
[ComplexType]
public class EFInt64Collection : EFPrimitiveCollection<long>
{
public override long ConvertFromString(string value) => long.Parse(value);
public override string ConvertToString(long value) => value.ToString();
}
[ComplexType]
public class EFStringCollection : EFPrimitiveCollection<string>
{
string _separator;
protected override string ValueSeparator => _separator ?? base.ValueSeparator;
public override string ConvertFromString(string value) => value;
public override string ConvertToString(string value) => value;
public EFStringCollection()
{
}
public EFStringCollection(string separator)
{
_separator = separator;
}
}
EFPrimitiveCollection works just like a list, so you shouldn't have any issues using it like a normal List. Also the data is loaded on demand.
Here's an example:
if (store.AcceptedZipCodes == null)
store.AcceptedZipCodes = new EFStringCollection();
store.AcceptedZipCodes.Clear();
store.AcceptedZipCodes.AddRange(codes.Select(x => x.Code));
Shadow Column
This attribute is being used to abstract away the Value property. If you do not see the need to do this, simply remove it and make the Value property public.
More information can be found on the ShadowColumnAttribute in my answer here
The simple solution would be in your DataContext (a class that implements DbContext) add this override:
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<MyObject>()
.Property(p => p.Numbers)
.HasConversion(
toDb => string.Join(",", toDb),
fromDb => fromDb.Split(',').Select(Int32.Parse).ToList() ?? new List<int>());
}

Serializability of enum-like class

I need to access an enum through a webservice.
As a webservice allocates 0 based integers to an enumeration (ignoring preset values in enum definition), I built the following:
public class StatusType
{
public StatusVal Pending { get { return new StatusVal( 1, "Pending"); } }
public StatusVal Authorised { get { return new StatusVal(2, "Authorised"); } }
public StatusVal Rejected { get { return new StatusVal(3, "Rejected"); } }
public StatusVal Sent { get { return new StatusVal(4, "Sent"); } }
public StatusVal InActive { get { return new StatusVal(5, "InActive"); } }
public List<StatusVal> StatusList()
{
List<StatusVal> returnVal = new List<StatusVal>();
StatusType sv = new StatusType();
returnVal.Add(sv.Pending);
returnVal.Add(sv.Authorised);
returnVal.Add(sv.Rejected);
returnVal.Add(sv.Sent);
returnVal.Add(sv.InActive);
return returnVal;
}
}
public class StatusVal
{
public StatusVal(int a, string b)
{
this.ID = a;
this.Name = b;
}
public int ID { get; set; }
public string Name { get; set; }
}
I then get the list of StatusVal with the following webmethod:
[WebMethod]
public List<ATBusiness.StatusVal> GetStatus()
{
ATBusiness.StatusType a = new ATBusiness.StatusType();
return a.StatusList();
}
I cannot however use this webmethod as referring it, I get the error: StatusVal cannot be serialized because it does not have a parameterless constructor.
I don't quite understand: should I pass params into the StatusValue type defined as the WebMethod's return Type?
I need this to return a list of StatusVals as per the StatusList() method.
As the error says, your class needs a constructor without parameters. When unserializing, the runtime will use that constructor instead of the one you have defined.
Something like:
public StatusVal()
{
}
When you created a constructor with parameters, you are automatically removing the default no-parameter constructor, and that's what the compiler is complaining about.