I have an Class Translator which has two instances of Parser(Options options) - an input parser, and output parser. They each get their own options.
Each parser has a list of ElementParser(Options option) which passes the options down.
If the each parser has a hundred elements, these means there are over a hundred refs to each option instance.
This seems excessive.
The obvious answer is to create a static Parser.Options property, but traditional wisdom says to stay away from them.
So is there a better way to architect this?
Here is a working sample:
public class Options {
public int Value { get; set; }
}
public class ElementParser {
public object ElementData { get; set; }
public ElementParser(Options options) {
this.Options = options;
}
public Options Options { get; set; }
public void DoesSomethingWithOptions() {
if (Options.Value == 1)
{
//Do something();
}
else
{
//Do something else();
}
}
}
public class SegmentParser{
public object SegmentData { get; set; }
public Options Options { get; set; }
public List<ElementParser> ElementParsers { get; set; }
public SegmentParser(Options options) {
this.Options = options;
}
public void AddABunchOfElements() {
this.ElementParsers = new List<ElementParser>() {new ElementParser(this.Options), new ElementParser(this.Options)};
}
}
class Program
{
static void Main(string[] args) {
var options1 = new Options() {Value = 1};
var options2 = new Options() {Value = 2};
var segment1 = new SegmentParser(options1);
segment1.AddABunchOfElements();
var segment2 = new SegmentParser(options2);
segment2.AddABunchOfElements();
//There are now 3 references of each options. If there were 100 elements, there would be over 200 references.
}
}
Here is a second attempt using a static property. Notice that the Parser class is subclassed, so there is really only one instance of the static property. This sample does work correctly.
public class Options
{
public int Value { get; set; }
}
public class Parser{
}
public class Parser1 : Parser
{
public Parser1(Options options) {
Options = options;
}
public static Options Options { get; set; }
}
public class Parser2 : Parser {
public Parser2(Options options) {
Options = options;
}
public static Options Options { get; set; }
}
class Program
{
static void Main(string[] args) {
var options1 = new Options();
options1.Value = 1;
var options2 = new Options();
options2.Value = 2;
var test1 = new Parser1(options1);
var test2 = new Parser2(options2);
Console.WriteLine(Parser1.Options.Value); //Should be 1
Console.WriteLine(Parser2.Options.Value); //Should be 2;
}
}
There's nothing wrong with what you've posted. A few hundred references to an object is not that big in the grand scheme of things.
I'd only make Options static if there is only one Options(which there isn't)
If Options is more associated with Segment than it is with Element than your Element might not even need to have the Options property, it can simply use Segment's or it can take an Options parameter in it's method.
Right now your program is abstracted enough that it's impossible to tell whether or not that would be appropriate, but it's something to keep in mind.
Segment and Element seem to be just plain DTO's, which should thus not be able with their own construction.
AddABunchOfElements() belongs in a SegmentWriter instance, containing one or more Options.
Related
I'm currently studying C# and I'm quiet stunned over a simple task.
I have this code to test:
public interface IAppointment
{
public string PatientName { get; set; }
public IEnumerable<DateTime> ProposedTimes { get; set; }
public DateTime? SelectedAppointmentTime { set; }
}
public static class MedicalScheduler
{
public static Dictionary<DateTime, string> Appointments { get; set; } = new Dictionary<DateTime, string>();
public static List<DateTime> FreeSlots { get; set; } = new List<DateTime>();
public static IEnumerable<Tuple<string, bool>> Schedule(IEnumerable<IAppointment> requests)
{
bool slotFound = false;
foreach (var appointment in requests)
{
if (slotFound) continue;
foreach (var times in appointment.ProposedTimes)
{
var freeSlot = FreeSlots.Where(s => s.Date == times.Date).FirstOrDefault();
if (freeSlot != null)
{
slotFound = true;
Appointments.Remove(freeSlot);
appointment.SelectedAppointmentTime = freeSlot;
yield return new Tuple<string, bool>(appointment.PatientName, true);
}
}
yield return new Tuple<string, bool>(appointment.PatientName, false);
}
}
}
And I'm required to test "Schedule" with a certain set of parameters. For example, I need to test it with empty Appointments and FreeList but with a single element in "requests".
I think I have understood how to compile a Unit Test and to set the Dictionary and List parameters. But I'm not sure how to create the IEnumerable variable.
My idea was to create a List of IAppointment(s), but how can I implement the interface in the test unit? I have tried using Moq but I didn't understood how I should use it correctly.
I'm sorry if the request seems quite confusing, but I don't know how to explain better :)
Thanks in advance for the help.
Please see the following example:
[Test]
public void Schedule()
{
// Arrange
var appointmentMock = new Mock<IAppointment>();
appointmentMock.Setup(appointment => appointment.PatientName).Returns("Dixie Dörner");
appointmentMock.Setup(appointment => appointment.ProposedTimes).Returns(
new List<DateTime>
{
new DateTime(1953,4,12),
new DateTime(1953,4,13)
});
var requests = new List<IAppointment>{appointmentMock.Object};
// Act
var results = MedicalScheduler.Schedule(requests);
// Assert
Assert.IsTrue(results.Any());
// results.Should().HaveCount(1); // If you're using FluentAssertions
}
MedicalScheduler.Schedule accepts any parameter implementing IEnumerable<IAppointment>, e. g. List<IAppointment> or Collection<IAppointment>.
So you simply create a List<IAppointment> and fill it with custom instances of IAppointment.
You can use Moq for creating the instances, as I did in the example. But for my own projects, I prefer the builder pattern:
internal static class AppointmentBuilder
{
public static IAppointment CreateDefault() => new Appointment();
public static IAppointment WithPatientName(this IAppointment appointment, string patientName)
{
appointment.PatientName = patientName;
return appointment;
}
public static IAppointment WithProposedTimes(this IAppointment appointment, params DateTime[] proposedTimes)
{
appointment.ProposedTimes = proposedTimes;
return appointment;
}
private class Appointment : IAppointment
{
public string PatientName { get; set; }
public IEnumerable<DateTime> ProposedTimes { get; set; }
public DateTime? SelectedAppointmentTime { get; set; }
}
}
[Test]
public void Schedule()
{
// Arrange
var requests = new List<IAppointment>{AppointmentBuilder.CreateDefault()
.WithPatientName("Dixie")
.WithProposedTimes(new DateTime(1953,4,12))};
// Act
var results = MedicalScheduler.Schedule(requests);
// Assert
Assert.IsTrue(results.Any());
// results.Should().HaveCount(1); // If you're using FluentAssertions
}
I am looking for information about that in the internet but with no success. The goal is to realize a sort of dataset of 10 subject (sub_1, sub_2... sub_10), each of them has done 3 kind of activities (walk, run, jump) for three time each (trial_1... trial_3) with relative scores. I would like to access these information like:
variable = dataset.sub_1.jump.trial_2.score;
or, at least:
variable = dataset.sub[0].task[2].trial[1].score;
So, the structure would be a tree structure. Until now I only realized a structure with "parallel fields":
struct dataset
{
public string[] sub; // 1 to 10 subjects
public string[] task; // 1 to 3 tasks
public string[] trial; // 1 to 3 trials
public int score; // the score of the above combination
}
Any idea?
This problem can be solved in many ways.
My solution has one drawback, there is no check if user exceeded Score arrays capacity.
I guess database tag has nothing to do with this question
using System;
using System.Linq;
namespace ConsoleApp
{
public abstract class Task
{
public string Name { get; set; }
public int TotalScore { get { return Score.Sum(); } }
public int[] Score { get; set; } = new int[3];
}
public class Walk : Task { }
public class Run : Task { }
public class Jump : Task { }
public class Subject
{
public Walk Walk { get; set; } = new();
public Run Run { get; set; } = new();
public Jump Jump { get; set; } = new();
public int TotalScore { get { return Walk.TotalScore + Run.TotalScore + Jump.TotalScore; }}
}
class Program
{
static void Main(string[] args)
{
var subject = new Subject();
// Adding score to specific trials
subject.Run.Score[0] = 50;
subject.Run.Score[1] = 40;
subject.Run.Score[2] = 60;
subject.Jump.Score[0] = 40;
subject.Jump.Score[1] = 80;
subject.Jump.Score[2] = 100;
// Output score of 1. trial for Walk task
Console.WriteLine(subject.Walk.Score[0]);
// Output total score as a sum of all trials for Jump task
Console.WriteLine(subject.Jump.TotalScore);
// Output total score as a sum of all trials in all tasks
Console.WriteLine(subject.TotalScore);
// ERROR CASE: this will be exception
subject.Jump.Score[3] = 100;
}
}
}
using System;
using System.Collections.Generic;
namespace ConsoleApp
{
public class Trial
{
public Trial(int score)
{
Score = score;
}
public int Score { get; set; }
}
public class Task
{
public List<Trial> Trials { get; } = new List<Trial>();
}
public class Subject
{
public Dictionary<string, Task> Tasks { get; } = new Dictionary<string, Task>();
public Subject()
{
Tasks.Add("walk", new Task());
Tasks.Add("run", new Task());
Tasks.Add("jump", new Task());
}
}
class Program
{
static void Main(string[] args)
{
Subject player1 = new Subject();
player1.Tasks["run"].Trials.Add(new Trial(score: 3));
Console.WriteLine(player1.Tasks["run"].Trials[0].Score);
}
}
}
Maybe a class for everything is too much, but maybe you want to add a description property for tasks one day or a timestamp for the trial. Then it's ok.
public class Subject
{
private Dictionary<string,Activity> _activities { get; }= new Dictionary<string, Activity>();
public Activity this[string activity]
{
get
{
if (!_activities.Keys.Contains(activity))
_activities[activity] = new Activity();
return _activities[activity];
}
set
{
_activities[activity] = value;
}
}
public int Score => _activities.Values.Sum(x => x.Score);
}
public class Activity
{
private Dictionary<int, Trial> _trials { get; } = new Dictionary<int, Trial>();
public Trial this[int trial]
{
get
{
if (!_trials.Keys.Contains(trial))
_trials[trial] = new Trial();
return _trials[trial];
}
set
{
_trials[trial] = value;
}
}
public int Score => _trials.Values.Sum(x => x.Score);
}
public class Trial
{
public int Score { get; set; }
}
public class Answer
{
public void DoSomething()
{
Subject Mindy = new Subject();
Mindy["curling"][1].Score = 5;
Mindy["bowling"][1].Score = 290;
Console.WriteLine(Mindy.Score);
}
}
This is what I would guess you think you need... but from your question I think you're still new to C# and might want to rethink your concept. It looks like a very database-oriented way of looking at the problem, so maybe you might want to take a look at dapper to more closely match your database.
Also, avoid using the classname Task, this can imo only cause confusion if you ever start using multithreading (System.Threading.Task is a .NET framework component)
I want to create a class with a property that "variably" points to some other property in another class.
Imagine a class (called "Limiter") with several integer properties (Limit1, Limit2, etc).
I now want a second class ("LimitWatcher") which can "watch" one of those limits. But I want to be able to set which particular limit it is watching in the constructor. I eventually want several instances of LimitWatcher, each one pointing to a separate Limit. The Limit values themselves may change after the Watchers have been instantiated, but the watcher must always see the current value of the Limit that it is watching. So basically, I want to store a reference to an integer.
I know I can accomplish this using reflection (see example below), but I feel as though there might be a simpler way.
using System;
namespace ConsoleApplication4
{
public class Limiter
{
public int limit1 { get; set; } = 10;
public int limit2 { get; set; } = 20;
public void Update()
{
limit1++;
limit2++;
}
}
public class LimitWatcher
{
public LimitWatcher(Limiter lim, string propName)
{
myLimiter = lim;
limitName = propName;
}
private Limiter myLimiter { get; }
public string limitName { get; set; }
//can I do this without reflection:
public int FooLimit { get { return (int)typeof(Limiter).GetProperty(limitName).GetValue(myLimiter); } }
}
class Program
{
static void Main(string[] args)
{
Limiter lim = new ConsoleApplication4.Limiter();
LimitWatcher w1 = new LimitWatcher(lim, nameof(lim.limit1));
LimitWatcher w2 = new LimitWatcher(lim, nameof(lim.limit2));
lim.Update();
Console.WriteLine($"1st watcher sees {w1.FooLimit}"); //11
Console.WriteLine($"2nd watcher sees {w2.FooLimit}"); //21
Console.ReadKey();
}
}
}
You could use a Func int the constructor, something like:
private Limiter limiter;
private Func<Limiter, int> propertyAccesor;
public LimitWatcher(Limiter lim, string propName, Func<Limiter, int> propertyAccesor)
{
this.propertyAccesor = propertyAccesor;
}
public bool LimitExceeded()
{
int propertyValue = propertyAccesor(limiter);
return propertyValue > 20;
}
You could use dynamic expressions:
using System.Linq.Expressions;
public class LimitWatcher
{
public LimitWatcher(Limiter lim, string propName)
{
myLimiter = lim;
limitName = propName;
var parameter = Expression.Parameter(typeof(Limiter), "x");
var member = Expression.Property(parameter, propName);
var finalExpression = Expression.Lambda<Func<Limiter, int>>(member, parameter);
getter = finalExpression.Compile();
}
private Func<Limiter, int> getter;
private Limiter myLimiter { get; }
public string limitName { get; set; }
public int FooLimit { get { return getter(myLimiter); } }
}
Inspired by this article
I have a multilingual database, which returns values based on a key and an enum Language. When I convert a DB object to a model, I want the model to contain the translated value based on the key and the current language.
The key comes from the DB object but how can I pass the current language to the the Mapper.Map() function?
Currently, I am using a [ThreadStatic] attribute to set the culture before calling Mapper.Map<>, and to retrieve it in the TypeConverter.
public enum Language
{
English, French, Italian, Maltese
}
public class MultilingualValue<T>
{
public Dictionary<Language, T> Value { get; set; }
public MultilingualValue()
{
this.Value = new Dictionary<Language, T>();
}
}
public class PersonData
{
public string FirstName { get; set; }
public MultilingualValue<string> City { get; set; }
}
public void MapPerson()
{
PersonData personData = new PersonData();
personData.FirstName = "John";
personData.City = new MultilingualValue<string>();
personData.City.Value[ Language.English] = "The Zurrieq";
personData.City.Value[Language.French] = "Le Zurrieque";
MultilingualValueData.CurrentLanguage = Language.English;
var personModel = Mapper.Map<PersonData, PersonModel>(personData);
}
public class MultilingualValueToBasicDataTypeConverter<T> : ITypeConverter<MultilingualValue<T>, T>
{
public T Convert(ResolutionContext context)
{
var currentLanguage = MultilingualValueData.CurrentLanguage; //THIS IS THE [ThreadStatic] VARIABLE
if (currentLanguage == null) throw new InvalidOperationException("Please make sure to fill in CurrentLanguage");
MultilingualValue<T> sourceMultilingualValue = (MultilingualValue < T > )context.SourceValue;
T destinationValue = default(T);
if (sourceMultilingualValue != null)
{
destinationValue = sourceMultilingualValue.Value[currentLanguage.Value];
}
return destinationValue;
}
}
public static class MultilingualValueData
{
[ThreadStatic]
public static Language? CurrentLanguage;
}
I left out the configurations as I think they're unneccessary for this example. If you need them, I'll post them as well.
While this works, I find this workaround quite ugly. Is there any way to pass data through the ResolutionContext?
Just use the Map overload that takes a Action<IMappingOperationOptions>. You can add configuration elements to the Items property that are then passed to your ITypeConverter
public class CustomConverter : ITypeConverter<string, string>
{
public string Convert(ResolutionContext context)
{
return "translated in " + context.Options.Items["language"];
}
}
internal class Program
{
private static void Main(string[] args)
{
AutoMapper.Mapper.CreateMap<string, string>().ConvertUsing<CustomConverter>();
var result = AutoMapper.Mapper.Map<string, string>("value" , opt => opt.Items["language"] = "english");
Console.Write(result); // prints "translated in english"
Console.ReadLine();
}
}
Please excuse bursts of stupidity as I learn the intricacies of C# / .NET
Say I have three classes with multiple static properties (more than three but for arguments sake..)
CLASS FOO
public static A
{
get / set A;
}
public static B
{
get / set B;
}
public static C
{
get / set C;
}
CLASS BAR
{
get / set A;
}
public static B
{
get / set B;
}
public static C
{
get / set C;
}
CLASS YOO
{
get / set A;
}
public static B
{
get / set B;
}
public static C
{
get / set C;
}
And from another class I need to update one or several static properties in each class multiple times... How do I keep from writing multiple SWITCH statments like this...
public void updateVarx(string class, string varx)
{
string y = 'class'
SWITCH (y)
{
case FOO:
FOO.A = Varx;
break;
case BAR:
BAR.A = Varx;
break;
case YOO:
YOO.A = Varx;
break;
}
}
And then another one when I want to update B varY:
public void updateVary(string class, string vary)
{
string y = 'class'
SWITCH (y)
{
case FOO:
FOO.B = Vary;
break;
case BAR:
BAR.B = Vary;
break;
case YOO:
YOO.B = Vary;
break;
}
}
Since you are learning .net/c#, I guess i should warn you, using static properties is probably not the way to go in object oriented programming.
Static is global state and is dangerous. If you end up using multi-threaded code, you have to be super careful. If you need only one instance, just instantiate one, but don't go creating static properties on a class, unless you have a pretty good reason to add them (And I can't think of any right now).
In fact, in well designed, object oriented code you sould probably not have many if, switch, getters or setters either.
Let's say you need different behaviors on your classes, you can do it this way.
Interface ISecurity {
void UpdateVarX(int value);
void UpdateVarY(int value);
int GetValueX();
int GetValueX();
}
class Foo:ISecurity {
// Implement methods of the interface
}
class Bar:ISecurity {
// Implement methods of the interface
}
class Yoo:ISecurity {
// Implement methods of the interface
}
// This class is the class that uses your other classes
class Consumer
{
private ISecurity sec;
public Consumer(ISecurity sec) {
sec.UpdateVarX(25);
}
}
Or if as in your example, all your static classes have the same properties:
public class Settings {
public int A {get; set;}
public int B {get; set;}
public int C {get; set;}
}
public class NeedsToUseOtherClass {
public NeedsToUseOtherClass() {
Settings foo = new Settings();
Settings bar = new Settings();
Settings yoo = new Settings();
foo.setA(25);
}
}
Maybe I am not understanding the problem but if all your classes have the same exact properties then you can just pass the object (FOO, BAR, or YOO) into UpdateVarx or UpdateVary methods and just implement an interface? Something along these lines:
public class FOO : IHasStatus
{
public A
{
get / set A;
}
public B
{
get / set B;
}
public C
{
get / set C;
}
}
public void updateVarx(IHasStatus someObject, string varx)
{
someObject.A = varx;
}
public void updateVary(IHasStatus someObject, string vary)
{
someObject.B = vary;
}
If you don't need the concrete classes, you can abstract out the logic like so:
public class Status {
public string A {
get; set;
}
public string B {
get; set;
}
public string C {
get; set;
}
}
public static class StatusManager {
private static Dictionary<string, Status> statusMap = new Dictionary<string,Status>();
public static Status GetStatus(string name) {
Status status;
if (!statusMap.TryGetValue(name, out status))
statusMap[name] = status = new Status();
return status;
}
public static void SetStatus(string name, Status status) {
statusMap[name] = status;
}
public static void UpdateVarx(string name, string varx) {
GetStatus(name).A = varx;
}
// ...
}
If you are a fan of the javascript way of solving multiple switch cases like this
you can always wrap up the switch handlers as Actions and toss them in a Dictionary.
For example : (Source obtained from here)
public class SwitchCase : Dictionary<string,Action>
{
public void Eval(string key)
{
if (this.ContainsKey(key))
this[key]();
else
this["default"]();
}
}
//Now, somewhere else
var mySwitch = new SwitchCase
{
{ "case1", ()=>Console.WriteLine("Case1 is executed") },
{ "case2", ()=>Console.WriteLine("Case2 is executed") },
{ "case3", ()=>Console.WriteLine("Case3 is executed") },
{ "case4", ()=>Console.WriteLine("Case4 is executed") },
{ "default",()=>Console.WriteLine("Default is executed") },
};
mySwitch.Eval(c);
Below code uses all kinds of hacks, not really recommended in production code unless you have a very good reason.
using System;
using System.Linq;
namespace ConsoleApplication1
{
static class Program
{
private static void SetStaticProperty(string className, string propName, string varx)
{
//This sucks, I couldnt find the namespace with easily through reflection :(
string NAMESPACE = "ConsoleApplication1";
Type t = Type.GetType(NAMESPACE + "." + className);
t.GetProperties().Where(p => p.Name == propName).First().SetValue(null, varx, null);
}
public static void updateVarx(string className, string varx)
{
SetStaticProperty(className, "A", varx);
}
public static void updateVary(string className, string vary)
{
SetStaticProperty(className, "B", vary);
}
static void Main(string[] args)
{
updateVarx("Foo", "FooAstring");
updateVarx("Bar", "BarAstring");
updateVarx("Yod", "YodAstring");
updateVary("Foo", "FooBstring");
updateVary("Bar", "BarBstring");
updateVary("Yod", "YodBstring");
Console.WriteLine(Foo.A);
Console.WriteLine(Foo.B);
Console.WriteLine(Bar.A);
Console.WriteLine(Bar.B);
Console.WriteLine(Yod.A);
Console.WriteLine(Yod.B);
Console.ReadLine();
}
}
class Foo
{
public static string A { get; set; }
public static string B { get; set; }
public static string C { get; set; }
}
class Bar
{
public static string A { get; set; }
public static string B { get; set; }
public static string C { get; set; }
}
class Yod
{
public static string A { get; set; }
public static string B { get; set; }
public static string C { get; set; }
}
}
You can use dictionary as configuration and remove the switch statement
Create a dictionary and add append data as below for mapping
//Have dictionary setted up
Dictionary<string, dynamic> m_Dictionary = new Dictionary<string, dynamic>();
m_xmlDictionary.Add("classA",FOO);
m_xmlDictionary.Add("classB",BAR);
m_xmlDictionary.Add("classC",BAR);
//Have dictionary setted up
//change the function as below
public void updatevarx(string class, string varx)
{
m_Dictionary[class].A=varx // Replaced switch statement
}
//while calling use
updatevarx("classC","abc!");// This will assign BAR.A with abc!