Generic parameter problem - c#

I have a business model which consists of a parent/child relationship (Identifier/IdentifierValue) and also some snapshot classes which look the same (IdentifierSnapshot/IdentifierValueSnapshot).
I am trying to create an extension method which will work on an enumeration of either Identifier or IdentifierSnapshot, but I just can't work out what to put in the extension method where I have inserted the XXX placeholder.
//Interfaces
public interface IIdentifier<TIdentifierValue>
where TIdentifierValue : IIdentifierValue
{
string Code { get; }
IEnumerable<TIdentifierValue> GetValues();
}
public interface IIdentifierValue
{
string Code { get; }
string Value { get; }
}
//Main classes
public class Identifier : IIdentifier<IdentifierValue>
{
public string Code { get; set; }
public IEnumerable<IdentifierValue> GetValues();
}
public class IdentifierValue : IIdentifierValue
{
public string Code { get; set; }
public string Value { get; set; }
}
//Snapshots
public class IdentifierSnapshot : IIdentifier<IdentifierValueSnapshot>
{
public string Code { get; set; }
public IEnumerable<IdentifierValueSnapshot> GetValues();
}
public class IdentifierValueSnapshot : IIdentifierValue
{
public string Code { get; set; }
public string Value { get; set; }
}
public static IdentifierExtensions
{
public static IEnumerable<XXX> ByCode<XXX>(this IEnumerable<XXX> instance, string code)
{
return instance.Where(x => string.Compare(code, x.Code, true) == 0);
}
}

I think this would do it:
public static IEnumerable<T> ByCode<T,Z>(this IEnumerable<T> instance, string code)
where T:IIdentifier<Z>
where Z:IIdentifierValue

Related

How to use Generic Delegate to access Derived Class Members?

Let me preface by saying I am new to coding and C# is my first language
I have a interface:
public interface ITDXInput <TSCContext, TContext, TWaferContainer> : ITDXInput
{
TSCContext SCContext { get; set; }
TContext ToolContext { get; set; }
TWaferContainer WaferContainer { get; set; }
}
This class implements the interface:
public class CIMTDXInput : ITDXInput<CIMSCContext, CIMToolContext, CIMWaferContainer>
{
public CIMWaferContainer WaferContainer { get; set; }
public CIMSCContext SCContext { get; set; }
public CIMToolContext ToolContext { get; set; }
}
The members of this class inherit from the following interfaces:
public class CIMSCContext : ISCContext
{
public string PROCESSING_END_TIME { get; set; }
public string PRODUCT_NAME { get; set; }
public string QUANTITY_IN { get; set; }
public string LOT_OWNER { get; set; }
public string FW_VERSION { get; set; }
}
public class CIMToolContext : IToolContext
{
public string LOT { get; set; }
public string TDX_MULTI_FILES { get; set; }
public string PROCESSING_START_TIME { get; set; }
public string WITHIN_UNIT_AXIS_DIRECTION { get; set; }
}
public class CIMWaferContainer : IWaferContainer
{
public CIMWaferContext WaferContext = new CIMWaferContext();
public List<CIMWaferImage> ImageList = new List<CIMWaferImage>();
public List<CIMWaferDieResults> WaferResultList = new List<CIMWaferDieResults>();
}
I have a delegate handling class:
public class KlarfTemplateDelegateHandler
{
public static Dictionary<string, Delegate> HandlerMap = new Dictionary<string, Delegate>();
public static Dictionary<string, Delegate> DefectListHandlerMap = new Dictionary<string, Delegate>();
delegate string TemplateDelegate<T,U,V>(ITDXInput<T, U, V> cimInput);
delegate string DefectListTemplateDelegate(CIMTDXInput cimInput, List<CIMKlarfDefectList> list);
static KlarfTemplateDelegateHandler()
{
HandlerMap["#DATA.TOOL_CONTEXT.PROCESSING_END_TIME_DATE#"] = new TemplateDelegate<ISCContext,IToolContext, IWaferContainer>(ProcessEndDate);
HandlerMap["#DATA.TOOL_CONTEXT.PROCESSING_END_TIME_TIME#"] = new TemplateDelegate(ProcessEndTime);
}
private static string ProcessEndDate<T,U,V>(ITDXInput<T,U,V> cimInput)
{
DateTime dateTime = DateTime.Parse(cimInput.ToolContext.PROCESSING_END_TIME);
//return cimInput.CIMSCContext.PROCESSING_END_TIME.Split(' ')[0];
return dateTime.ToString("MM-dd-yyyy");
}
}
The issue is that for the function ProcessEndDate, it tells me that 'T' does not contain a definition for "PROCESSING_END_TIME_TIME". I tried to replace TSCContext inside ITDXInput with ISCContext as the generic for the ITDXInput's TSCContext but it's localized.
Is there anything I can do to be able to get the function to see that whatever ITDXInput I pass into the ProcessEndDate function will have the PROCESSING_END_TIME_TIME definition?
I am going through this exercise because I would like to reuse that delegatehandler class for other types of TDXInput
One approach would be to constrain the ProcessEndDate method. A minimal example of this would be to have this interface:
public interface ISCContext
{
string PROCESSING_END_TIME { get; set; }
}
with two different classes that implement it:
public class ClassA : ISCContext
{
public string PROCESSING_END_TIME { get; set; } = "A:" + DateTime.UtcNow.ToString();
}
public class ClassB : ISCContext
{
public string PROCESSING_END_TIME { get; set; } = "B:" + DateTime.UtcNow.ToString();
}
To let the compiler know what to expect in a generic method, you would use the keyword where to make an interface constraint. For clarity, I made a new method with only 1 generic argument. You could, of course, have multiple arguments and corresponding constraints to define expectations for T, U and V but this gives you the basic idea.
private static void showProcessingEndTime<T>(T item) where T : ISCContext
{
Console.WriteLine(item.PROCESSING_END_TIME);
}
Here's a Microsoft article explaining the many ways Generic Type Constraints may be used.
Test code
static void Main(string[] args)
{
var a = new ClassA();
showProcessingEndTime(a);
var b = new ClassB();
showProcessingEndTime(b);
}

C# how to match generic types from different classes

On one hand I have a list of capabilities, for example:
public interface ICapability
{
public string Name { get; }
}
public class RangeCapability<T> : ICapability
{
public string Name { get; set; }
public T Min { get; set; }
public T Max { get; set; }
}
public class SetCapability<T>
{
public string Name { get; set; }
public HashSet<T> Set { get; set; }
}
On the other hand I have a list of requirements
public interface IRequirement
{
public string Name { get; }
}
public class Requirement<T> : IRequirement
{
public string Name { get; set; }
public T Value { get; set; }
}
Both capability list may contain capabilities of different types T and requirement list may contain requirements of different types. The important thing is that if for a given name the underlying types match I should check if value is between min and max (for range class) or in a set like in the example below:
public class Entity
{
List<ICapability> Capabilities { get; set; }
public bool IsSatisfying(List<IRequirement> requirements)
{
foreach(var requirement in requirements)
{
var capability = Capabilities.FirstOrDefault(x => x.Name == requirement .Name);
//how to check if here if types match and if req. within range or in collection?
}
}
}
I am not sure how to match generic types of two different classes and then do the check suitable for the apropriate implementation (is within range/is present in set). Can somebody point me in the right direction how could I make it work?
I believe this is what you're looking for. Make the interfaces generic and also make the Entity class generic.
public interface INamed<T>
{
string Name { get; }
}
public interface ICapability<T> : INamed<T>
{
}
public class RangeCapability<T> : ICapability<T>
{
public string Name { get; set; }
public T Min { get; set; }
public T Max { get; set; }
}
public class SetCapability<T>
{
public string Name { get; set; }
public HashSet<T> Set { get; set; }
}
public interface IRequirement<T> : INamed<T>
{
}
public class Requirement<T> : IRequirement<T>
{
public string Name { get; set; }
public T Value { get; set; }
}
public class Entity<T>
{
List<ICapability<T>> Capabilities { get; set; }
public bool IsSatisfying(List<IRequirement<T>> requirements)
{
foreach (var requirement in requirements)
{
var capability = Capabilities.FirstOrDefault(x => x.Name == requirement.Name);
//how to check if here if types match and if req. within range or in collection?
if(capability is INamed<T>)
{
Console.WriteLine("types match");
}
}
}
}

C#. Universal desition for storing different types

I'm looking for the best approach of working with different types identically.
I have a web service that goes to specific resource, makes some research and returns an object WebResult, that contains all information about completed operations.
And now I'd like to build a set of different metrics, that will describe all received results. These metrics should provide
different types of data
easy way to collect it
possibility to deserialize it.
Example 1
First I've created separate classes for different metrics
public abstract class AbstractStatistic
{
public string Url { get; set; }
public string ExceptionMessage { get; set; }
public abstract void FillAllMetrics(WebResult result);
}
public class Resource1Statistic : AbstractStatistic
{
public string Title { get; set; }
public string[] Table1_Header { get; set; }
public int Table1_RowCount { get; set; }
public string[] Table2_Header { get; set; }
public int Table2_RowCount { get; set; }
public override void FillAllMetrics(WebResult result)
{
this.Url = result.url;
this.Title = result.data["title"];
this.Table1_Header = result.data["table1.header"].ToObject<string[]>();
//...
}
}
It works, but I'd like to make it in more standard way. One of the reason is that in this approach I have to create separate web form for each metrics.
Example 2
Second working example is universal but redundant: create an abstraction of any datatype
public abstract class AbstractStatistic
{
public string Url { get; set; }
public string Exception { get; set; }
public Dictionary<string, Metric> Metrics { get ;set;}
public abstract void FillAllMetrics(WebResult webResult);
}
public class Metric // Specific class for data
{
public string StringValue { get; set; }
public int? IntegerValue { get; set; }
public string[] ArrayValue { get; set; }
public DateTime? DateTimeValue { get; set; }
}
public class Resource1Statistic : AbstractStatistic
{
public override void FillAllMetrics(WebResult result)
{
this.Metrics.Add("title",
new Metric() { StringValue = result.data["title"].ToString() });
this.Metrics.Add("Table1 Header",
new Metric() { ArrayValue = result.data["table1.header"].ToObject<string[]>() });
//...
}
It works, but I'm sure there is more elegant solution. I don't like to take all these null values in json.
Examples 3
Generic solution (regarding to Adwaenyth)
public abstract class AbstractStatistic
{
public string Url { get; set; }
public string Exception { get; set; }
public List<AbstractMetric> Metrics { get ;set;}
public abstract void FillAllMetrics(WebResult webResult);
}
public abstract class AbstractMetric{}
public class Metric<T> : AbstractMetric
{
public string Name { get; set; }
public T Value { get; set; }
public string Type { get; private set; }
public Metric()
{
this.Type = typeof(T).ToString();
}
}
public class Resource1Statistic : AbstractStatistic
{
public override void FillAllMetrics(WebResult result)
{
this.Metrics.Add(new Metric<string>()
{ Name = "title",
Value = result.data["title"].ToString() });
this.Metrics.Add(new Metric<string[]>()
{ Name = "Table1 Header",
Value = result.data["table1.header"].ToObject<string[]>() });
//...
}
This solution looks nice, but I have to write custom deserializer.
What do you think, is there some good pattern that fits to my task? Or what's the best approach?

How to go about combining two objects, manipulate the data, then separate them?

I have two classes with some similar fields, some different, and a form that utilizes two different objects depending on what mode it's in (insert/edit).
Instead of using two different objects and if statements checking the form mode, I'd like to have one struct to be hydrated with either of the two objects fields so I can manipulate one object through the page life-cycle. Then separated the struct back to its respective object for insert/updating the DB.
Example of classes:
public partial class SomeClass
{
public Int32 B {get;set;}
public String C {get;set;}
public Boolean D {get;set;}
}
public class SomeOtherClass
{
public Int32 A {get;set;}
public Int32 B {get;set;}
public String C {get;set;}
}
Update with Solution Example:
public interface IInsertable
{
string SharedName { get; set; }
string SharedID { get; set; }
string editedFieldValue { get; set; }
long GetSuperSecreteInfo();
}
internal class InsertableImplementation : IInsertable
{
public string SharedName { get; set; }
public string SharedID { get; set; }
public string editedFieldValue { get; set; }
public long GetSuperSecreteInfo()
{
return -1;
}
}
public interface IUpdateable
{
string SharedName { get; set; }
string SharedID { get; set; }
string updatedFieldValue { get; set; }
Guid GenerateStevesMagicGuid();
}
internal class UpdateableImplementation : IUpdateable
{
public string SharedName { get; set; }
public string SharedID { get; set; }
public string updatedFieldValue { get; set; }
public Guid GenerateStevesMagicGuid()
{
return new Guid();
}
}
public static class WonderTwinFactory
{
public static WonderTwins GenerateWonderTwin(IUpdateable updateable, IInsertable insertable)
{
var wt = new WonderTwins();
// who will win?
wt.SharedID = updateable.SharedID;
wt.SharedID = insertable.SharedID;
// you decide?
wt.SharedName = updateable.SharedName;
wt.editedFieldValue = "stuff";
return wt;
}
}
public class WonderTwins : IInsertable, IUpdateable
{
public string SharedName { get; set; }
public string SharedID { get; set; }
public string editedFieldValue { get; set; }
public long GetSuperSecreteInfo()
{
return 1;
}
public string updatedFieldValue { get; set; }
public Guid GenerateStevesMagicGuid()
{
return new Guid();
}
}
class Program
{
static void Main(string[] args)
{
IUpdateable updateable = new UpdateableImplementation();
IInsertable insertable = new InsertableImplementation();
WonderTwins dualImplementatin = WonderTwinFactory.GenerateWonderTwin(updateable, insertable);
IUpdateable newUpdateable = dualImplementatin as IUpdateable;
IInsertable newInsertable = dualImplementatin as IInsertable;
}
}
Have both classes implement an interface that defines the operations common to each, including both the fields that are shared (assuming the view needs to access them) and also a method to actually perform the operation that they represent (insert/edit).
Other way of doing such things is using C# dynamic object and assign properties directly. It may help to avoid any new type or interface and directly utilizing new dynamic object any time, as much as required.
var newObject = new {
objectOfClass1 = x.prop1,
objectOfClass2 = x.prop2
}

JSONDeserializer from Json string to List of objects

I'm new on java/android:
I'm using this list of objects on wp7 and I want pass to android, how I do this:
My big object c#:
public class ListCountries
{
public List<CountriesRepresented> _countriesRepresented { get; set; }
public List<CountriesOrigin > _countriesOrigin { get; set; }
}
My others two objects in c#:
public class CountriesRepresented
{
public int CountryID { get; set; }
public string Designation { get; set; }
public string Symbol { get; set; }
public string NomDesignationISO { get; set; }
}
public class CountriesOrigin
{
public int CountryID { get; set; }
public string Designation { get; set; }
public string Symbol { get; set; }
public string NomDesignationISO { get; set; }
}
My java Deserializer:
public Object[] getListCountries()
{
try {
HttpClient httpClient = new DefaultHttpClient();
HttpPost post = new HttpPost(Config.WS_PATH);
post.setHeader("content-type", "application/json; charset=UTF-8");
post.addHeader("Client-Application","3601cfde-e440-4a84-a2cc-a402f4c7bd14");
HttpResponse resp = httpClient.execute(post);
String respStr = EntityUtils.toString(resp.getEntity());
ListCountries _listCountries = new JSONDeserializer().deserialize(ListCountries .class, respStr);
return _listCountries;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
My big object in java:
public class ListCountries {
public List<CountriesRepresented> _CountriesRepresented;
public List<CountriesOrigin > _CountriesOrigin ;
public List<CountriesRepresented> getCountriesRepresented() {
return this._CountriesRepresented;
}
public List<CountriesOrigin > getCountriesOrigin() {
return this._CountriesOrigin ;
}
public void setCountriesRepresented (List<CountriesRepresented> CountriesRepresented) {
this._CountriesRepresented = CountriesRepresented;
}
public void setCountriesOrigin (List<CountriesOrigin > CountriesOrigin ) {
this._CountriesOrigin = CountriesOrigin ;
}
}
My service is on WebAPI and give me an correct answer example: `{"PaisesRepresentantes":[{"PaisID":4,"Designacao":"Alemanha","Sigla":"DEU","NomDesignacaoISO":"GERMANY"},{"PaisID":21,.......
your classes in Java should be something like,
public class ListCountries
{
public List<CountriesRepresented> _countriesRepresented; //Make it private if you want and then you can add getter setter function
public List<CountriesOrigin > _countriesOrigin;
}
public class CountriesRepresented
{
public int CountryID; //Make it private if you want and then you can add getter setter function
public String Designation;
public String Symbol;
public String NomDesignationISO;
}
public class CountriesOrigin
{
public int CountryID; //Make it private if you want and then you can add getter setter function
public String Designation;
public String Symbol;
public String NomDesignationISO;
}
The problem with your existing code is that you have declared variable as _CountriesRepresented rather it should be _countriesRepresented i.e. properties are case sensitive and those are mapped to variables declared in class and do remember to add a default constructor if you add any custom constructor to any of those classes

Categories