My issue is, cannot create auto generated instance from the interface.
Here is my example:
public class SomeClass {
public string TestName { get; set; }
}
// And then I call like this
var obj = new Fixture().Create<SomeClass>();
Concrete class is generated automatically and it's properties like this:
Console.WriteLine(obj.TestName);
// Output: TestNameb7c3f872-9286-419f-bb0a-c4b0194b6bc8
But I have an interface like below:
public interface ISomeInterface
{
string TestName { get; set; }
}
// And then I call like this
var obj = new Fixture().Create<ISomeInterface >();
It is generated but it's properties is not set.
Console.WriteLine(obj.TestName);
// Output: null
How can I create an instance from the interface like the concrete class?
Agree with Mathew Watson comment, this question might already be answered in the mentioned question.
Just wanted to share my version which is slightly different from those answer from 2012 ;)
public interface ISomeInterface
{
string TestName { get; set; }
}
public class SomeClass : ISomeInterface
{
public string TestName { get; set; }
}
public class Test
{
[Fact]
public void Do()
{
var fixture = new Fixture();
fixture.Customize<ISomeInterface>(x => x.FromFactory(() => new SomeClass()));
var result = fixture.Create<ISomeInterface>();
Console.Out.WriteLine("result = {0}", result.TestName);
// output:
// result = TestName2c7e6902-d959-46ce-a79f-bf933bcb5b7f
}
}
Of course, AutoMoq or AutoNSubstitute are the options to consider.
Related
I have an API providing tons of functionality, thatswhy there are massive abstractions to generics.
Please imagine (with the code below) following scenario: Every Dto has an Id. I want to test against a Service, create the items. The service doenst know the Id, because it gets generated by the DbContext.
So far so regualar.
But now imagine, i have a nested Dto, like in the example ComplexDto contains a SampleDto. So my TestHelper should test all the IDto, and ignore ALL Ids (the one of ComplexDto AND SampleDto), just by having the Interface.
DTO-Setup:
public interface IDto
{
long Id { get; }
}
public abstract record BaseDto : IDto
{
public long Id { get; init; }
}
public sealed record SampleDto : BaseDto
{
public string FooString { get; init; } = string.Empty;
}
public sealed record ComplexDto : BaseDto
{
public string AnotherFooString { get; init; } = string.Empty;
public SampleDto SampleDto { get; init; } = default!;
}
Test-Setup
[Test]
public void TestDummy()
{
var dto = new ComplexDto()
{
Id = 1, // for demo porposes
SampleDto = new SampleDto
{
Id = 1, // for demo porposes
FooString = "hi"
}
};
var testHelper = new TestHelper<ComplexDto>();
testHelper.CheckStuff(dto);
}
public class TestHelper<IDto>
{
public void CheckStuff(IDto dto)
{
var anotherDto = new ComplexDto()
{
Id = 123, // for demo porposes
SampleDto = new SampleDto
{
Id = 123, // for demo porposes
FooString = "hi"
}
};
//fails
//ComplexDto.Id gets ignored
//SampleDto.Id does not get ignored!!!
anotherDto.Should().BeEquivalentTo(dto, options => options.Excluding(x => x.Id));
}
}
So actually, what i am looking for, is in FluentAssertions-Api something like ExcludeAll("Id") or ExcludeRecursive("Id"). I could help myself with some ugly reflection, but maybe there is a "good" solution for this?
Help is appreciated <3
I didnt find any solution yet. Instead of "ignoring" the test-values, i went with "improved" seeding for the IDs.
Really hard, by setting them in a generic way with SpecimenBuilders (in AutoFixture), but anyhow it works.
I have a class like this
public class OwnerWithholding
{
private decimal ManagementFeePct;
private decimal TotalManagementFee;
private decimal OperationalFeesPct;
private decimal TotalOperationalFees;
}
And I have calculation method that create object of this class, fill it with some arithmetic operations, and return this object.
public OwnerWithholding CalculationMethod1(Reservation r, SqlConnection conn)
{
OwnerWithholding result = new OwnerWithholding();
// result.ManagementFeePct = some data from Fees table in DB + value
//from another db - constant value..
// Also with other properties - with some operations on data
//result.TotalManagementFee = ..
// result.OperationalFeesPct = ..
// result. TotalOperationalFees = ..
return result;
}
And now it works fine.
But this calculation method is just one option for populating data.
There is another calculation method, implemented in a completely different way, but filling exactly the same properties of the object. And I may have more of them.
I need a pattern that would allow me to create objects of the same class, just indicating the calculation method that is needed.
I like the strategy pattern , where the algorithms will be the methods that fill the objects that called them.
But it doesn’t look very good.
Maybe a factory method would be more appropriate here, but I don’t know how to implement it.
Edit: Going by the OPs comments now, it looks like just ONE method in the class needs to be set in multiple ways.
The Template pattern (or the Builder) are better fits in this case, not the Factory.
Template Pattern.
a. Abstract Base class that set default properties, but leaves out one property (Get Ingredients) to be populated by the concrete classes.
public abstract class PizzaCreator
{
public abstract string GetIngredients { get; }
public string Bake { get; set; } = "Bake at 400F for 30 minutes";
public string Deliver { get; set; } = "Deliver in custom box";
}
b. Two Pizza classes, for now just overriding the abstract property
public class CheesePizza : PizzaCreator
{
public override string GetIngredients
{
get { return GetMyIngredients(); }
}
string GetMyIngredients()
{
return "Lots of Cheese!";
}
}
public class PepperoniPizza : PizzaCreator
{
public override string GetIngredients
{
get { return GetMyIngredients(); }
}
string GetMyIngredients()
{
return "Lots of Meats!";
}
}
Here I'm creating instances of the Pizza
var pepPizza = new PepperoniPizza();
var chessePizza = new CheesePizza();
You could even have these creations routed through a Factory class/method.
Original answer:
Here is the Abstract Factory Pattern.
This code goes into the Factory class library.
a.ICar interface
public interface ICar
{
string Name { get; set; }
int Doors { get; set; }
string EngineCapacity { get; set; }
}
b.Abstract Car Factory
public abstract class AbstractCarFactory
{
public abstract ICar CreateCar(CarType type);
}
c.Two Concrete Cars -
internal class NissanPickUpTruck : ICar
{
public string Name { get; set; }
public int Doors { get; set ; }
public string EngineCapacity { get ; set ; }
}
internal class NissanSportsCar: ICar
{
public string Name { get; set; }
public int Doors { get; set; }
public string EngineCapacity { get; set; }
}
d.Concrete Factory
public class NissanFactory : AbstractCarFactory
{
public override ICar CreateCar(CarType type)
{
switch (type)
{
case CarType.PickupTruck:
return new NissanPickUpTruck{Name = "Titan", Doors = 6, EngineCapacity = "V12"};
case CarType.SportsCar:
return new NissanSportsCar{Name = "350Z", Doors = 2, EngineCapacity = "V6"};
default:
throw new Exception();
}
}
}
Finally the calls from an external project
var nissanFactory = new NissanFactory();
var sportsCar = nissanFactory.CreateCar(CarType.SportsCar);
var pickUpTruck = nissanFactory.CreateCar(CarType.PickupTruck);
But like the other comment, the Builder is something worth checking out as well.
I have an Interface and it is implemented by many classes. Each class also has its own set of properties which are not present in interface. Now, if I want to design a factory which returns of type interface, I cannot set some of the derived class properties as they are not member of interface.
How to address this scenario?
If you have an Interface like
public interface MyInterface
{
string Name { get; }
}
and implementations like
public class MyClass : MyInterface
{
string Name { get; set; }
int Something { get; set; }
}
public class MySecondClass : MyInterface
{
string Name { get; set; }
decimal SomethingElse { get; set; }
}
you can create your class in the factory like
public class MyFactory
{
public MyInterface createMyClass()
{
return new MyClass() { Name = "foo", Something = 42 };
}
public MyInterface createMySecondClass()
{
return new MySecondClass() { Name = "bar", SomethingElse = 4.2M };
}
}
Of course this way you can't access the members you don't have declared in your interface.
var something = myFactory.createMyClass().Something;
This wouldn't work. You can only access the name property:
var name = myFactory.createMyClass().Name;
If you would want to access the special property of your class, you would have to cast your interface to the actual class:
var something = ((MyClass)myFactory.createMyClass()).Something;
I would like to create a generic method that can convert an object to a different type. I could not find any solutions for this scenario. Is this possible in C#?
class A
{
public string Name { get; set; }
}
class A1: A
{
public string ConnectionString { get; set; }
}
class B
{
public string DBName { get; set; }
public string DBConnectionString { get; set; }
}
void Main()
{
A obj = //data
var res = APIToBackEndModel<A, B>(obj);
//Do something
A1 obj1 = //data
var res1 = APIToBackEndModel<A1, B>(obj1);
}
private TResult APIToBackEndModel<T, TResult>(T objTo)
{
(TResult)DBName = (T)objTo.Name;
//OR
var obj = new TResult
{
DBName = (T)objTo.Name
}
}
This did not help me.
You won't be able to do it completely generic, as you rely on certain properties to exist. But you knowing these properties exist, is not enough. You have to guarantee the compiler, they exist. You can do this with Constraints on type parameters. With their help, you can define, that the generic types you use, will have certain properties (for instance implement an interface or inherit from a class).
interface InterfaceIn {
string p1 {get;set;}
void m1();
}
interface InterfaceOut {
string p2 {get;set;}
void m2();
}
class ConcreteIn : InterfaceIn {
public string p1 {get;set;}
public void m1() {}
}
class ConcreteOut1 : InterfaceOut {
public string p2 {get;set;}
public void m2() {}
}
class ConcreteOut2 : InterfaceOut {
public string p2 {get;set;}
public void m2() {}
}
class Program
{
static void Main(string[] args)
{
var a = new ConcreteIn{p1 = "some value"};
var b = mapIt<ConcreteIn, ConcreteOut1>(a);
var c = mapIt<ConcreteIn, ConcreteOut2>(a);
}
public static V mapIt<U, V>(U val) where U: InterfaceIn where V: InterfaceOut, new() {
var res = new V {p2 = val.p1};
return res;
}
}
Depending on how much properties and combinations you have, this may be enough. Or you may be better off with something like Automapper as Hans Kesting suggested. Or, if you can't group together some mappings, you will have to implement every mapping yourself.
I've got this piece of code to create new objects in a generic way:
var user = User.Create<User>(c => c.Name = "321X");
What I don't like about it is the fact I need to pass the 'generic notation' <T> for every create call. After all I create an object that I'm already referring to...
The code behind this current functionality is:
public class User : CreateBase
{
public string Name { get; set; }
}
public abstract class CreateBase
{
public DateTime CreateDate { get; set; }
public Guid Guid { get; set; }
public static T Create<T>(Action<T> init) where T : CreateBase, new()
{
T obj = new T();
obj.Guid = Guid.NewGuid();
obj.DateTime = DateTime.Now;
init(obj);
return obj;
}
}
Is it possible (and how) to refactor my code to this, to create an object?
var user = User.Create(c => c.Name = "321X");
Thanks!
Define the generic argument on the class level:
public abstract class CreateBase<T> where T : CreateBase<T> , new()
{
public static T Create(Action<T> init)
{
//...
}
}
public class User : CreateBase<User>
{
public string Name { get; set; }
}
Then you can write var user = User.Create(c => c.Name = "321X");
Otherwise the compiler cannot infer the type for your Create method without specifying the type argument.
You were not very far. Try this modification:
public abstract class CreateBase<T> where T : CreateBase<T> , new()
{
public DateTime CreateDate { get; set; }
public Guid Guid { get; set; }
public static T Create(Action<T> init)
{
T obj = new T();
obj.Guid = Guid.NewGuid();
obj.CreateDate = DateTime.Now;
init(obj);
return obj;
}
}
public class User : CreateBase<User>
{
public string Name { get; set; }
}
EDIT: Updated the code after I tested it on my local environment. It works now.
You are doing it the wrong way. Instead of getting rid of the generic argument, get rid of (needlessly) saying User.. Instead:
CreateBase.Create<User>(...)
No more redundancies.
Besides that, calling a static member of the base class through a derived class is an anti-pattern.
A better approach would be to include this functionality in the constructor of the base class (I call it ModelBase)
public abstract class ModelBase
{
public DateTime CreateDate { get; private set; }
public Guid Guid { get; private set; }
public ModelBase()
{
Guid = Guid.NewGuid();
DateTime = DateTime.Now;
}
}
public User : ModelBase
{
public User()
: base()
{
}
public User(string name)
: base()
{
Name = name
}
public string Name { get; set; }
}
Creating a user the standard way will initialize the Guid and date automatically
var user = new User { Name = "xy };
EDIT
I added a second constructor with a name parameter. I you want to force the initialization of the name, drop the first parameterless constructor.
var user = new User("xy");
If you really uncomfortable with that sintax (I, honestly, don't see much problem here)
you can do the following:
public class User : CreateBase
{
public string Name { get; set; }
public static User Create(Action<User> a)
{
return Create<User>(a); //CALL BASE CLASS GENERIC FUNCTION
}
}
After you can call it in a way you would like to do that :
var user = User.Create(c => c.Name = "321X");