I'm trying to create a method which can be used like this:
Assembler.CreateTransfer(i);
i is an item inside a dynamic collection.
i is a domain object.
CreateTransfer() should return an instance of i type + Transfer (if my domain object is User, then it should return an instance of UserTransfer.
As for my models is like this:
public abstract class UserBase {
public long UserId { get; set; }
public string Username { get; set; }
}
public class UserTransfer : UserBase, ITransferObject { }
public partial class User : UserTransfer, IModelBase, IDomainObject {
public User() {
Roles = new List<Role>();
}
public virtual ICollection<Role> Roles { get; set; }
}
So far, I've accomplished this:
public static TTransfer CreateTransfer<TTransfer, TDomain>(TDomain d)
where TTransfer : ITransferObject
where TDomain : IDomainObject
{ ... }
This works, because I know the type of TTransfer and TDomain.
And I can call it like: CreateTransfer<UserTransfer, User>(d).
The problem comes when I try create the dto without specifying any type:
CreateTransfer(d);
Of course I've added an overload for this task and I hope I can magically accomplish the following:
public static ITransferObject CreateTransfer(IDomainObject d) {
// do magic
return CreateTransfer<transfer, domain>(d);
}
But in the real world, this is as far as I could get:
public static ITransferObject CreateTransfer(IDomainObject d) {
var dType = d.GetType();
var assemblyName = dType.Assembly.FullName;
var domainName = dType.FullName;
var transferName = domainName + "Transfer";
var domain = Activator.CreateInstance(assemblyName, domainName).UnWrap();
var transfer = Activator.CreateInstance(assemblyName, transferName).UnWrap();
return CreateTransfer< ?, ?>(d); // Problem
}
Both domain and transfer objects are being created correctly.
The main question is: Is there any way to be able to call CreateTransfer<domain, transfer>(d)? Any help will be appreciated.
You can use reflection to call the generic method.
Something like this:
var method = typeof(ClassThatDefinesCreateTransfer)
.GetMethods()
.Single(x => x.Name == "CreateTransfer" &&
x.IsGenericMethodDefinition)
.MakeGenericMethod(dType, transferType);
return (ITransferObject )method.Invoke(null, new object[] { d });
You probably want to cache at least the result of typeof(ClassThatDefinesCreateTransfer).GetMethods().
Related
I've seen a few questions like this floating around but I'm looking for a good explination of how to get around this. I understand that Moq can't mock the extension call, but I'm just looking for a really good example. In the current code I there is a call like
var thing = listOfthings.myList.SingleOrDefault(lt => lt.Name== "NameToFind");
I've tried
MockedlistOfThings.Setup(x => x.myList.SingleOrDefault(o => o.Name == "NameToFind")).Returns(fakeObject);
Just looking for a good work around. thanks.
To further elaborate on how this situation came up, we are currently running a translation engine against large sets of data, that has to be run line by line. This translation engine passes in an Interface called IListOfthings. listOfthings is actually holding reference data in a dictionary that is preloaded in another call higher up in the program. I have created a "fakeObject" <- dictionary that holds my fake data that the method can use. I have Mocked the IlistOfthings which is passed in to the calling method. but I don't see how to fake the SingleOrDefault call.
Simplifed method below.
Public class ClassIMTesting
{
public void Translate(myObject obj, IlistOfThings listOfthings){
var thing = listOfthings.MyList.SingleOrDefault(lt => lt.Name== "NameToFind");
//Other logic here .....
}
}
public class Thing()
{
public string Name { get; set; }
public Dictionary MyDict { get; set; }
}
[TestFixture()]
public class MyCodeTest
{
MyObject myObj;
Mock<IListOfthings> listOfThings;
Thing thing;
[SetUp]
public void Setup()
{
myObj = new MyObject();
_thing = new thing();
_thing.Name = "MyName";
var myDict = new Dictionary<string, string>();
myDict.Add("70,~", "");
myDict.Add("70,145", "expectedResult");
myDict.Add("911,", "expectedResult");
thing.MyDict = myDict;
listOfThings = new Mock<IListOfthings>();
listOfThings.Setup(x => x.MyList.SingleOrDefault(o => o.Name == "MyName")).Returns(thing);
}
[TestCase("70", "~", "70070")]
[TestCase("70", "145", "expectedResult")]
[TestCase("911", "", "expectedResult")]
public void TranslateTest(string iTC, string ITCode, string expectedResult)
{
myObject.ITC = iTC;
myObject.ITCode = iTCode;
ClassIMTesting p = new ClassIMTesting();
p.Translate(myObject, listofThings.Object);
Assert.That(myObject.ITC3Code, Is.EqualTo(expectedResult));
}
}
public interface IListOfThings
{
List<Thing> MyList{ get; set; }
}
Given
public interface IListOfThings {
List<Thing> MyList { get; set; }
}
public class Thing() {
public string Name { get; set; }
public Dictionary MyDict { get; set; }
}
In order to provide a mock to satisfy the following example
public class ClassImTesting {
public Thing Translate(IlistOfThings listOfthings){
var thing = listOfthings.MyList.SingleOrDefault(lt => lt.Name== "NameToFind");
return thing
}
}
The mock just needs to return a collection that will allow the SingleOrDefault extension to behave as expected when invoked.
For example
//Arrrange
Mock<IListOfthings> listOfThings = new Mock<IListOfthings>();
var thing = new Thing {
Name = "NameToFind",
//...
};
List<Thing> list = new List<Thing>() { thing };
listOfThings.Setup(_ => _.MyList).Returns(list);
var subject = new ClassImTesting();
//Act
var actual = subject.Translate(listOfThings.Object);
//Assert
Assert.That(actual, Is.EqualTo(thing));
By having the mock return an actual List<Thing>, when
var thing = listOfthings.MyList.SingleOrDefault(lt => lt.Name== "NameToFind");
is invoked, the SingleOrDefault extension acts on a list where I can behave as expected.
I have class named ResponseModel and one object inside that class named Errors refer to the class ErrorsResponseModel, and that class has bunch of objects which have List<string> data type . I would like to know on how to accessing the List<string> objects without going through like: VariableClassA.ObjectOfClassAWhichReferToTheClassB.FirstListOfString and VariableClassA.ObjectOfClassAWhichReferToTheClassB.SecondListOfString, the data of List<string> objects comes from the JSON data.
I have tried only to access one object per one object as I am not really sure on how to do generic without going through one object per one object, which is if I update the model of class B itself, then I need to make sure that I didn't missed out the necessary checking of that newly created object inside class B.
Here is the code of the model:
public sealed class ResponseModel
{
public ErrorsResponseModel Errors { get; set; }
}
public sealed class ErrorsResponseModel
{
public List<string> Username { get; set; }
public List<string> Password { get; set; }
public List<string> Nickname { get; set; }
}
Here is what I have tried so far:
string jsonData = "{"Errors":{"Username":["The username field is required."],"Password":["The password field is required."],"Nickname":["The nickname field is required."]}}";
var jsonConvertedData = JsonConvert.DeserializeObject<ResponseModel>(jsonData);
var usernameErrors = jsonConvertedData.Errors.Username;
var passwordErrors = jsonConvertedData.Errors.Password;
var nicknameErrors = jsonConvertedData.Errors.Nickname;
I expect to loop any object of class ErrorsResponseModel that the length of List<string> inside that class is more than 0 . I can't change the response data from the JSON, as it is comes from the third party.
EDIT: I have tried the following in JavaScript and it works, how can I do the same in C#?
in C#, I return to the front end like using the following return Json(jsonConvertedData), and in frontend, I do like the following:
$.ajax({
..... the AJAX settings
success: function (data) {
$.each(data.Errors, function (i, v) {
if (v.length > 0) {
console.log(v);
}
});
}
The above code in Javascript is looping through the message inside each object inside ErrorsResponseModel and read it through to the console.
Let ErrorsResponseModel inherit Dictionary
public sealed class ErrorsResponseModel : Dictionary<string, List<string>>
{
//If you still want to access data with property.
public List<string> Username => this["Username"];
...
}
Now you can loop through Errors like a normal dictionary
foreach (var item in jsonConvertedData.Errors)
if(item.Value.Count > 0)
Console.WriteLine($"{item.Key} => {item.Value[0]}");
dynamic is another choice
var jsonConvertedData = JsonConvert.DeserializeObject<dynamic>(jsonData);
foreach (var item in jsonConvertedData.Errors)
if(item.Count > 0)
foreach(var v in item.Value)
Console.WriteLine(v);
One way to do this would be to create a class to hold the related data, for example:
class User
{
public string Name { get; set; }
public string Nickname { get; set; }
public string Password { get; set; }
}
Then we can make a method that populates a list of this class from the ErrorsResponseModel class (after first validating that the counts of all the lists are the same):
public List<User> GetUsers(ErrorsResponseModel errors)
{
if (errors == null || errors.Username == null) return null;
if (errors.Username.Count == 0) return new List<User>();
if (errors.Nickname?.Count != errors.Password?.Count ||
errors.Password?.Count != errors.Username.Count)
{
throw new InvalidDataException("Unequal number of Usernames/Passwords/Nicknames");
}
return errors.Username
.Select((userName, index) =>
new User
{
Name = userName,
Nickname = errors.Nickname[index],
Password = errors.Password[index]
}).ToList();
}
I am trying to make a function that works with a list of an interface but I would like to keep the concrete class values for those lists. For example:
public interface GUID_OBJECT
{
string GUID { get; set; }
}
public class Car : GUID_OBJECT
{
public string GUID { get; set; }
public string CarSpecifikProp { get; set; }
}
public class Bike : GUID_OBJECT
{
public string GUID { get; set; }
public string BikeSpecifikProp { get; set; }
}
class Program
{
static void Main(string[] args)
{
var cars = new List<Car>() { new Car() { GUID = "1", CarSpecifikProp = "carstuff" }, new Car() { GUID = "2", CarSpecifikProp = "carsuff" } };
var bikes = new List<Bike>() { new Bike() { GUID = "1", BikeSpecifikProp = "bikestuff" }, new Bike() { GUID = "2", BikeSpecifikProp = "bikestuff" } };
var filteredCars = FilterGuidObjects(cars);
foreach (var car in filteredCars)
{
car.CarSpecifikProp = "changethis";
}
var filteredBikes = FilterGuidObjects(bikes);
foreach (var bike in filteredBikes)
{
bike.BikeSpecifikProp = "changethis";
}
Console.ReadKey();
}
static List<GUID_OBJECT> FilterGuidObjects(List<GUID_OBJECT> objects)
{
return objects.Where(x => x.GUID == "1").ToList();
}
}
This code doesn't work but it illustrates what I would like to do. I have a web api project that returns various type of lists of objects, but all these objects have some things in common such as GUID for example. Can I write functions that work with the interface GUID_OBJECT but keep the Car and Bike specific properties after that function returns its List of GUID_OBJECT interfaces? How would you deal with a scenario like this?
make a generic method with a constraint:
static List<G> FilterGuidObjects<G>(List<G> objects) where G: GUID_OBJECT
{
return objects.Where(x => x.GUID == "1").ToList();
}
The point of interfaces is to have only the common properties of the classes that implement them. If you need to use a specific property you'll need to cast to the type you want:
var obj = (MyType) myInterface
Since you're working with lists, you can cast the entire list like this:
listOfInterface.Cast<MyType>().ToList()
Consider implementing FilterGuidObjects as a generic function:
static List<T> FilterGuidObjects<T>(List<T> objects) where T : GUID_OBJECT
{
return objects.Where(x => x.GUID == "1").ToList();
}
there are many ways of achieving this but the crux of the matter is you have to convert the interface back to the original type
Method 1: generic filter on the function
static List<T> FilterGuidObjects(List<T> objects)
:where T:GUID_OBJECT
{
return objects.Where(x => x.GUID == "1").ToList();
}
Pros Quick and simple, will even infer the type automatically
Cons you can't feed in a Mixed list
Method 2 Type Filter the collection
var filteredCars = FilterGuidObjects(MixedListOfVechiles).OfType<Car>();
Pros Can handle mixed lists
Con have to specify the conversion every time
Method 3 Convert the Type Directly
var car = guid_object as Car
if(car != null)
car.CarSpecifikProp = "changethis";
or
if(guid_object is Car)
{
var car = (Car)guid_object
car.CarSpecifikProp = "changethis";
}
Pros doesn't use generics
Con requires lots of code
I have a base class called BaseStatus which looks like this:
public class BaseStatus
{
public int UnitId { get; protected set; }
public UInt16 StatusValue { get; protected set; }
public string StatusCode { get; protected set; }
public string StatusDescription { get; protected set; }
public BaseStatus()
{
this.UnitId = -1;
this.StatusValue = 0;
this.StatusCode = null;
this.StatusDescription = null;
}
}
Furthermore i have two or more other base classes which derive from BaseStatus and define a other unit id. For example the two classes
public class BaseGlobalStatus : BaseStatus
{
public BaseGlobalStatus()
{
base.UnitId = -1;
}
}
public class BaseGcmGdmStatus : BaseStatus
{
public BaseGcmGdmStatus()
{
base.UnitId = 2;
}
}
public class BaseCcuStatus : BaseStatus
{
public BaseCcuStatus()
{
base.UnitId = 1;
}
}
The Background is that i want to derive from for example BaseCcuStatus and have the correct UnitId in the derived class.
Now i define my correct status classes for example:
public class StatStErrDefinition : BaseGlobalStatus
{
public StatStErrDefinition()
: base()
{
base.StatusDescription = "Kommando nicht zulässig, unit im state ERROR";
base.StatusCode = "STAT_ST_ERR";
base.StatusValue = 3;
}
}
public class GcmStErrDefinition : BaseGcmGdmStatus
{
public GcmStErrDefinition()
: base()
{
base.StatusDescription = "Kommando nicht zulässig, unit im state ERROR";
base.StatusCode = "STAT_ST_ERR";
base.StatusValue = 3;
}
}
public class CcuStErrDefinition : BaseCcuStatus
{
public CcuStErrDefinition()
: base()
{
base.StatusDescription = "Kommando nicht zulässig, unit im state ERROR";
base.StatusCode = "STAT_ST_ERR";
base.StatusValue = 3;
}
}
For my understading, the three classes StatStErrDefinition, GcmStErrDefinition and CcuStErrDefinition should have the UnitId which is set in the derived BaseClass?
Now that i have defined my three Status Classes i want to get them into a registry. Currently im using this piece of code to try get them. Problem is that the result has no items.
registry = new StatusDictionary<UInt16, BaseStatus>();
var unitStatus = typeof(BaseStatus)
.Assembly.GetTypes()
.Where(x => x.BaseType == typeof(BaseStatus))
.Select(x => new
{
StatusType = x,
UnitId = x.GetProperty("UnitId", BindingFlags.Public)
StatVal = x.GetProperty("StatusValue", BindingFlags.Public)
}
)
.Where(x => x.StatVal != null && x.UnitId != null)
.Select(x => new
{
UnitId = (int)x.UnitId.GetValue(null, null),
StatusValue = (UInt16)x.StatVal.GetValue(null, null),
Factory = (Func<BaseStatus>)(() => ((BaseStatus)Activator.CreateInstance(x.StatusType)))
});
try
{
foreach (var status in unitStatus)
{
if (status.UnitId == unitId
|| status.UnitId < 0)
registry.Register(status.StatusValue, status.Factory);
}
}
catch (Exception ex)
{
string temp = ex.Message;
}
After the LINQ expression the var unitStatus is empty...
Later, the registry call looks like that to get the specific class but that is unimportant at this point:
stat = StatusContainer.GetRegistry(this.unitTypeId).GetInstance(this.StatusValue);
For information:
I want to get the status class which should be in the registry by the unittypeid and the specific status value.
Currently my registry method does not work because he is not able to find any class. So there has to be a mistake somewhere. Thanks in advance
#Update 1
I changed my functionality a little bit:
registry = new StatusDictionary<UInt16, BaseStatus>();
//get all types of cucrent assembly
var allAssemblyTypes = Assembly.GetCallingAssembly().GetTypes();
//get all types from base status
var baseStatusTypes = allAssemblyTypes.Where(x => x.BaseType == typeof(BaseStatus));
//Place all concrete types in the foundtypes
List<Type> foundTypes = new List<Type>();
foreach (Type item in baseStatusTypes)
{
var temp = allAssemblyTypes.Where(x => x.BaseType == item)
.Select(x => new
{
StatusType = x,
UnitId = x.GetProperty("UnitId", BindingFlags.Public),
StatVal = x.GetProperty("StatusValue", BindingFlags.Public),
}
);
}
Temp contains now the correct type.
Problem is that if temp is type of StatStErrDefinition the StatusValue and UnitId Property is null.
The fact is that these members are instance members. Is there a way to get the values out of them?
First thing first : your LINQ query is pretty long.
divide it in different step and store them in different variables (or make properties out of them, whatever you prefer)
This is
easy to read / maintain
easy to debug
With this given I think you are able to solve your problem :)
To check if the class is of a certain type you could use the method .OfType
Use this method to get the value. Notice that you must make an instance in your case because the value change in your constructor.
public static object GetPropValue(Type src, string propName)
{
var prop = src.GetProperty(propName);
var instance = Activator.CreateInstance(src);
var value = prop.GetValue(instance);
return value;
}
Instead of
UnitId = x.GetProperty("UnitId", BindingFlags.Public),
use
UnitId = GetPropValue(x,"UnitId"),
I have a reflection method finds all the types in a namespace:
var models =
Assembly.GetAssembly(application).GetTypes().Where(
#t => #t.Namespace == typeof(ViewModelNamespaceBeacon).Namespace).OrderBy(#m => #m.Name).ToList();
My problem is I'm returning an Anonymous type with the name of:
{Name = "<>c__DisplayClass2" FullName = "UCHC.CFAR.Web.Models.FieldSecurityViewModel+<>c__DisplayClass2"}
Now from what I've seen detecting anonymous types are difficult( 1141874 ) but I can always filter "funky" names, ie .Contains("<>c_ ") so thats not a big deal.
I'm just trying to find this anonymous type so I can refactor it away. The namespace I'm inspecting is my ViewModel namespace and should be free of too much logic. Now given I've just said that I do have one ViewModel which does perform some logic ( is a mid-refactoring of a couple of other helper classes ) and seems to be identified by name in the name of my anonymous type:
public List<string> Roles { get; private set; }
public IEnumerable<SelectListItem> ViewModelSelectList { get; private set; }
public List<SecurityRule> SecurityRules { get; set; }
public Type SelectedViewModel { get; set; }
public FieldSecurityViewModel(IEnumerable<string> roles,
IEnumerable<Type> viewModels,
string selectedViewModelName = ""
)
{
SetFilteredRoles(roles);
SetViewModelSelectList(viewModels, selectedViewModelName);
}
private void SetViewModelSelectList(IEnumerable<Type> viewModels, string selectedViewModelName)
{
ViewModelSelectList = from v in viewModels
select new SelectListItem()
{
Selected = v.Name == selectedViewModelName,
Text = GenerateFriendlyViewModelName(v.Name),
Value = v.Name
};
return;
}
private void SetFilteredRoles(IEnumerable<string> roles)
{
Roles = roles.Where(#a => !#a.EndsWith("Admin") && !#a.EndsWith("NonFacultyUsers") && #a.StartsWith("CFAR.")).ToList();
}
public static string GenerateFriendlyViewModelName(string typeName)
{
var result = typeName.Replace("ViewModel", "")
.Replace("GridViewModel", "")
.Replace("EditViewModel", "")
.Replace("GridModel", "");
return result.HumanizeCamel();
}
public IEnumerable<ModelMetadata> GetProperties()
{
if (SelectedViewModel == null)
return new List<ModelMetadata>();
var properties = ModelMetadataProviders.Current.GetMetadataForType(null, SelectedViewModel).Properties;
return properties.Where(#p => !#p.PropertyName.EndsWith("PK_ID") && !#p.PropertyName.StartsWith("FK_") && !#p.PropertyName.EndsWith("_PK"));
}
I just can't find the anon type in there.
A "...DisplayClass" is usually associated with an anonymous method that needs to capture variables.
In this case, I'm betting on the lambda expression associated with the "select new SelectListItem()", since you're referring to the parameter to the method.
Try commenting out the contents of the SetViewModelSelectList method, and see if the anonymous type disappears.