I have this situation:
List<Details> trace;
private class Details
{
public string date { get; set; }
public string type { get; set; }
public string mex { get; set; }
}
private class Context
{
public List<object> context { get; set; }
}
how can I insert in the trace list the class Details and Context? My goal is create a multidimensional list that have as key the class properties such as: date, type, mex, context and as value a dynamic content.
You can use for that purpose an abstraction contract between both classes...
for example if both classes implement a new interface, lets say MyCustomInterface that you define, then declare the list as List<MyCustomInterface> trace; and then you can add objects of both classes...
Example:
List<MyCustomInterface> trace;
private class Details: MyCustomInterface
{
public string date { get; set; }
public string type { get; set; }
public string mex { get; set; }
}
private class Context:MyCustomInterface
{
public List<object> context { get; set; }
}
then you can always do
trace.Add(new Context(...));
trace.Add(new Details(...));
You can use Tuple<Details, Context> to hold instance of either as item in the list, but then when iterating items you will then have to use Item1 and such names to access underlying values:
List<Tuple<Details, Context>> trace;
// add
trace.Add(new Tuple(new Details(), new Context()));
// iterate
foreach(var item in trace)
if(item.Item1?.date == ... && item.Item2?.context != null) { ... }
A better idea might be to construct own type to hold both: Details and Context instance (as properties with same names):
class ContextDetails
{
public Context { get; set; }
public Details { get; set; }
// todo: add constructor to simplify constructing items when adding
}
and use it
List<ContextDetails> trace;
// add
trace.Add(new ContextDetails()
{
Details = new Details(),
Context = new Context(),
});
// iterate
foreach(var item in trace)
if(item.Details?.date == ... && item.Context?.context != null) { ... }
Hmm if you really wanted to have both in a List, i'd give you two options:
First:
Create a parent-Class which both inherit.
Next step is to put the name of the parent class into your List.
Both will fit if they were extended by the same parent class
Second:
Create an Objekt that contains a Context and Details object and put that into the list.
Related
I know this has been answered a lot of places on stack and the best possible answer is Here. I've tried it and a lot of other answers too. I have a library that returns me a collection of an Interface (IMasterAutoSuggestOutlet)
public interface IMasterAutoSuggestOutlet : IBaseAutoSuggestOutlet
{
IAddressData AddressData { get; }
IPlaceActivity PlaceActivity { get; }
string ELoc { get; }
Geopoint ExactLocation { get; }
Geopoint EntranceLocation { get; }
LocationType TypeOfLocation { get; }
}
Now, I want to transfer this interface data from one page to another in my application. Since Interfaces cannot be serialized, I created a concrete class that implements this interface:
My Concrete Class,
public class MasterAutoSuggestModel : IMasterAutoSuggestOutlet
{
public IAddressData AddressData { get; set; }
public IPlaceActivity PlaceActivity { get; set; }
public string ELoc { get; set; }
public Geopoint ExactLocation { get; set; }
public Geopoint EntranceLocation { get; set; }
public LocationType TypeOfLocation { get; set; }
}
What I want to do is, convert the ICollection to ICollection. My code below shows my implementation of such an operation:
var collection = mainPageViewModel?.SearchPageVM?.searchManager?.AutoSuggestResponse;
var ob = collection.First();
if (ob is IMasterAutoSuggestOutlet)
{
var ToBeTransfered = collection.OfType<MasterAutoSuggestModel>(); //Simply returns the collection with a count 0
var serializedData = JsonConvert.SerializeObject(ToBeTransfered);
ScenarioFrame.Navigate(typeof(MasterSearchResultPage), serializedData);
}
The issue is with var ToBeTransfered = col.OfType<MasterAutoSuggestModel>(); it returns me a collection with count 0 even though the collection has 10 items in it.
Can someone please tell me where am I going wrong? Please note I need to use this Converted collection to serialize and send as the navigation parameter to send to the next page
The ofType method filters the connection by the type specified. If you are retrieving the objects from some other library, they would not be that specific type.
https://msdn.microsoft.com/en-us/library/bb360913(v=vs.110).aspx
What you would probably want to do is convert the items retrieved from the library into your dto for serialisation. You can use something like automapper for the conversion
if (ob is IMasterAutoSuggestOutlet) {
var transferObject = new MasterAutoSuggestModel(){
//Set Properties
}
// var ToBeTransfered = collection.OfType<MasterAutoSuggestModel>(); //Simply returns the collection with a count 0
var serializedData = JsonConvert.SerializeObject(transferObject);
ScenarioFrame.Navigate(typeof(MasterSearchResultPage), serializedData); }
I have a weird situation where I have objects and Lists of objects as part of my entities and contracts to interface with a third-party service. I'm going to try to see if I can replace the actual object class with something more specific in the entities and contracts to get around this, but I am curious if there is a way to get AutoMapper to handle this as is.
Here are some dummy classes:
public class From
{
public object Item { get; set; }
}
public class FromObject
{
public string Value { get; set; }
}
public class To
{
public object Item { get; set; }
}
public class ToObject
{
public string Value { get; set; }
}
And the quick replication:
Mapper.CreateMap<From, To>();
Mapper.CreateMap<FromObject, ToObject>();
From from = new From { Item = new FromObject { Value = "Test" } };
To to = Mapper.Map<To>(from);
string type = to.Item.GetType().Name; // FromObject
Basically, the question is this: Is there a way to get AutoMapper to understand that from.Item is a FromObject and apply the mapping to ToObject? I'm thinking there's probably not a way to make it automatic, since there's nothing that would indicate that to.Item has to be a ToObject, but is there a way to specify during the CreateMap or Map calls that this should be taken into account?
I don't think there is an "automatic" way of doing it, since AutoMapper won't be able to figure out that From.Item is FromObject and To.Item is ToObject.
But, while creating mapping, you can specify that
Mapper.CreateMap<FromObject, ToObject>();
Mapper.CreateMap<From, To>()
.ForMember(dest => dest.Item, opt => opt.MapFrom(src => Mapper.Map<ToObject>(src.Item)));
From from = new From { Item = new FromObject { Value = "Test" } };
To to = Mapper.Map<To>(from);
string type = to.Item.GetType().Name; // ToObject
If you're willing to use an additional interface, this can be accomplished using Include. You can't just map object to object in this fashion, though.
public class From
{
public IItem Item { get; set; }
}
public class FromObject : IItem
{
public string Value { get; set; }
}
public class To
{
public object Item { get; set; }
}
public class ToObject
{
public string Value { get; set; }
}
public interface IItem
{
// Nothing; just for grouping.
}
Mapper.CreateMap<From, To>();
Mapper.CreateMap<IItem, object>()
.Include<FromObject, ToObject>();
From from = new From { Item = new FromObject { Value = "Test" } };
To to = Mapper.Map<To>(from);
string type = to.Item.GetType().Name; // ToObject
I have an object containing different properties like the object below:
public class CompressedLogResponse
{
public string LoggerType { get; set; }
public int NumberOfRegisters { get; set; }
public int NewLogId { get; set; }
public DateTime LoggerAnnounceTime { get; set; }
public List<Log> Log{ get; set; }
}
How can I return a List of this objekt that does not include the List<Log> Log property?
Linq would be preffered
Thanks for any help that you can provide
You cannot just hide a property of a class (you declared it a as public)
Option 1:
Althought as Robson wrote you can set it null (thats not very reliable thaught cause nobody expects a class containing a property that is always null)
Option2:
If you consume the class on the same place use a anonymous type as Mez wrote, althought it sounds like you want to hide the Property from external usage. (I don't like the dynamic approach, the dynamic keyword was made for interop/DOM not for transporting anonymous types.)
Option3:
If you want a List of this type to be returned without the Log property, you have to create a new class (Inheritance is a good way to realize this):
public class CompressedLogResponseBase
{
public string LoggerType { get; set; }
public int NumberOfRegisters { get; set; }
public int NewLogId { get; set; }
public DateTime LoggerAnnounceTime { get; set; }
}
public class CompressedLogResponse : CompressedLogResponseBase
{
public List<Log> Log{ get; set; }
}
Now you can return a list of base items (that do not have a Log property at all)
public List<CompressedLogResponseBase> ReturnWithoutLog(IEnumerable<CompressedLogResponse> items)
{
return ((IEnumerable<CompressedLogResponseBase>)items).ToList();
}
If a IEnumerable as return type is suficient it becomes really easy
public IEnumerable<CompressedLogResponseBase> ReturnWithoutLog(IEnumerable<CompressedLogResponse> items)
{
return items
}
whith "does not include the List Log property" i guess you mean that the property "public List Log" will be blanked but still there, so you can just null that property out, because if you create an object that doesn't contain the "public List Log" property, than it will not be a "CompressedLogResponse" but will be another type.
List<CompressedLogResponse> listOne = new List<CompressedLogResponse>();
//....
//fill the listOne
//....
List<CompressedLogResponse> listWithoutListLog = (from item in listOne
select new CompressedLogResponse(
LoggerType = item.LoggerType,
NumberOfRegisters = item.NumberOfRegisters ,
NewLogId = item.NewLogId ,
LoggerAnnounceTime = item.LoggerAnnounceTime ,
Log= null)).ToList();
You can return an anonymous list of your original list like the following;
public static List<dynamic> Test() {
List<CompressedLogResponse> list = new List<CompressedLogResponse>();
var result = list.Select(x => new
{
x.LoggerAnnounceTime,
x.LoggerType,
x.NewLogId,
x.NumberOfRegisters
});
return result.ToList<dynamic>();
}
Take a look at the .Select(), and also the dynamic keyword.
Then to call it,
var x = Test();
foreach(dynamic o in x)
{
int NumberOfRegisters;
//You have 2 ways... either by
NumberOfRegisters = o.NumberOfRegisters;
// or reflection
NumberOfRegisters = o.GetType().GetProperty("NumberOfRegisters").GetValue(o, null);
}
I have two models; one holding the values of the fields that are displayed on the page and the other holding the required fields for that page depending on a user variable.(think of it as a combo box that for on each variable, different fields are rendered for the page). My question is what is the most efficient and manageable way to use those two models in a single view/controller? I tried to tuple them but I get that I need to create a parameter-less constructor error. Thank you.
As tarzanbappa said, one of the best approaches would be for you to add the extra fields in each ViewModel.
In order for you to not go into each ViewModel and add all the properties you need, you can add a variable instance of your other ViewModel.
For example: (Your ViewModels)
public class MyViewModel()
{
public T PropertyOne { get; set; }
public T PropertyTwo { get; set; }
public MyOtherViewModel PropertyThree { get; set; }
}
public class MyOtherViewModel()
{
public T PropertyOneCheck { get; set; }
public T PropertyTwoCheck { get; set; }
}
Then in your DataModel call, set your variable.
For Example: (LINQ)
...
PropertyThree = (from r in context.Table
where conditionIsMet
select new MyOtherViewModel
{
PropertyOneCheck = r.PropertyOneCheck,
PropertyTwoCheck = r.PropertyTwoCheck
}).FirstOrDefault();
...
And in your View You can toggle the visibility of fields as follows:
#if(Model.PropertyThree.PropertyOneCheck)
{
//Show Field
}else
{
//Hide Field
}
The best approach would be to have a view model designed specifically for the UI which, by the sounds of things, would be a hybrid of your two current models.
You can use DataAnnotations to add metadata to each property and then Validate your model e.g.
public class ViewModel
{
[Required]
public string PropertyOne { get; set; }
[Required]
public string PropertyTwo { get; set; }
}
...
var model = new ViewModel();
var results = new List<ValidationResult>();
if (!Validator.TryValidateObject(model, new ValidationContext(model), results)) {
Console.WriteLine("Model is not valid:");
foreach (var r in results) {
Console.WriteLine(r.ErrorMessage);
}
} else {
Console.WriteLine("Model is valid");
}
Live Example
I have two classes which contain the same fields, however one inherits some properties from somewhere else and the other does not.
I have created a generic list using the class "ZEUS_ResearchStocksHistory" , but then I need to clone all of the fields over to the other list "ZEUS_ResearchStocksHistoryWithExcel". I don't want to have to loop through each field in one list and populate the other, or write some sort of linq join, there must be a faster way?
The reason I can't use the same class in both instances is that when inheriting the ExcelReport function it adds additional fields which I do not want when I display this list in a data grid.
internal class ZEUS_ResearchStocksHistory
{
public String Amendment { get; set; }
public String AmendedBy { get; set; }
public String Sedol { get; set; }
public String Date { get; set; }
}
internal class ZEUS_ResearchStocksHistoryWithExcel : ExcelReport
{
public String Amendment { get; set; }
public String AmendedBy { get; set; }
public String Sedol { get; set; }
public String Date { get; set; }
}
Is this possible?
Thanks
Did you have a look at automapper?
example from codeproject:
CustomerViewItem customerViewItem =
Mapper.Map<Customer, CustomerViewItem>(customer);
Check out Automapper, which is designed to do exactly this. Automapper is up on NuGet.
http://lostechies.com/jimmybogard/2009/01/23/automapper-the-object-object-mapper/
You could do something as simple as:
Mapper.CreateMap<ZEUS_ResearchStocksHistory, ZEUS_ResearchStocksHistoryWithExcel>();
var newObject = Mapper.Map<ZEUS_ResearchStocksHistory, ZEUS_ResearchStocksHistoryWithExcel>(oldObject);
Or, since you said you have a list, you could do:
var newList = oldList.Select(x => Mapper.Map<ZEUS_ResearchStocksHistory, ZEUS_ResearchStocksHistoryWithExcel>(x));