How to access a property in another class? - c#

I am working with a WPF .Net Core 3 project.
In my UnbalancedViewModel I need to access an ID from another class (TestRunDto.cs).
UnbalancedViewModel
public class UnbalancedViewModel : ViewModelBase, IUnbalancedViewModel
{
private TestRunApi _testRunApi;
public UnbalancedViewModel(TestRunApi testRunApi, INotificationManager notifications)
{
_testRunApi = testRunApi;
}
private void StartTestRunJobExecuted(object obj)
{
_testRunApi.StartTestRun(1); ////I need the Id from TestRunDto (TestRunDto.Id)
}
}
TestRunApi
public async Task<TestRunLiveValueDto> GetTestRunLiveValue(int jobRunId)
{
await using var dbContext = new AldebaDbContext(_connectionString);
return await TestRunInteractor.GetTestRunLiveValue(jobRunId, dbContext);
}
public async Task StartTestRun(int testRunId)
{
await using var dbContext = new AldebaDbContext(_connectionString);
await TestRunInteractor.StartTestRun(dbContext, testRunId);
}
TestRunLiveValueDto
public class TestRunLiveValueDto
{
public TestRunDto TestRun { get; }
public bool ShowInstantaneousValue { get; set; }
public bool EnableStart { get; set; }
public bool EnableStop { get; set; }
public bool EnableMeasure { get; set; }
public int RecipeRpm { get; }
public string ActualRecipeName { get; }
public int DefaultSetOfPlaneId { get; }
public ICollection<BalancePlaneDto> ListBalancePlane { get; }
public ICollection<SetOfPlaneDto> ListSetOfPlane { get; }
public ICollection<SensorVibrationDto> SensorVibrations { get; set; }
public ICollection<EstimationDto> InstantaneousValues { get; set; }
public ICollection<EstimationDto> EstimationsValues { get; set; }
private TestRunLiveValueDto(TestRunDto testRun, bool enableStart, bool enableStop, int recipeRpm, ICollection<SensorVibrationDto> sensorVibrations)
{
EnableStart = enableStart;
EnableStop = enableStop;
TestRun = testRun;
RecipeRpm = recipeRpm;
SensorVibrations = sensorVibrations;
}
public static TestRunLiveValueDto Create(TestRunDto testRun, bool enableStart, bool enableStop, int recipeRpm, ICollection<SensorVibrationDto> sensorVibrations)
=> new TestRunLiveValueDto(testRun, enableStart, enableStop, recipeRpm, sensorVibrations);
}
TestRunDto
public class TestRunDto
{
public int Id { get; set; }
public int JobRunId { get; set; }
public string Name { get; set; }
public int TestRunNumber { get; set; }
public RunState State { get; set; }
public ICollection<BalancePlaneDto> BalancePlanes { get; set; } // Todo remove
private TestRunDto(int id, int jobRunId, RunState state, string name, int testRunNumber)
{
Id = id;
JobRunId = jobRunId;
Name = name;
TestRunNumber = testRunNumber;
State = state;
}
public static TestRunDto Create(int id, int jobRunId, RunState state, string name, int testRunNumber)
=> new TestRunDto(id, jobRunId, state, name, testRunNumber);
}
I have been trying to understand this, but I can not get a hold of the proper method to do this. Do I first declare a new TestRunDto class in my viewmodel or am I supposed to access it some other way?

You need to ensure class A has a reference to an instance of class B to access the properties, for example one way of doing this is to pass class A to B in a method where you can manipulate or access properties.
public class FooA
{
public string PropertyA { get; set; }
}
public class FooB
{
public string PropertyB { get; set; }
public void CanAccessFooA(FooA a)
{
a.PropertyA = "See, I can access this here";
}
}
Another is to pass class A to B in the constructor (known as dependency-injection)
public class FooB
{
FooA _a;
public FooB(FooA a)
{
// Pass instance of FooA to constructor
// (inject dependency) and store as a member variable
this._a = a;
}
public string PropertB { get; set; }
public void CanAccessFooA()
{
if (this._a != null)
this._a.PropertyA = "See, I can access this here";
}
}
Exactly how to structure your code is up to you, but the principle remains the same: Class B can only access Class A if it has a reference to an instance of it.
Look into 'Dependency Injection' as there are many techniques to achieve this.
Edit
One such technique might be abstracting the code to provide the ID to both, like so
public class IdProvider
{
public int Id { get; set; }
}
public class FooA
{
private int _id;
public FooA(IdProvider idProvider)
{
_id = idProvider.Id;
}
}
public class FooB
{
private int _id;
public FooB(IdProvider idProvider)
{
_id = idProvider.Id;
}
}
Now both classes have the same ID;

StartTestRun takes the tesRunId as it's parameter.
public async Task StartTestRun(int testRunId)
{
I think you need to call StartTestRunJobExecuted with this testRunId.
You will to change
private void StartTestRunJobExecuted(object obj)
to
private void StartTestRunJobExecuted(int testRunIdn)
{
_testRunApi.StartTestRun(testRunId); ////I need the Id from TestRunDto (TestRunDto.Id)
}
(This based on me guessing).

Related

Project a name-value list into an object

I want to be able to save an arbitrary flat object into the name-value list.
public class NameValueListEntity
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[InverseProperty(nameof(NameValueListContentEntity.Entity))]
public ICollection<NameValueListContentEntity> Content { get; set; }
}
public class NameValueListContent
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[ForeignKey("entity_fk")]
public NameValueListEntity Entity { get; set; }
public string Name { get; set; }
public string Value { get; set; }
}
public class ObjectToSave
{
public string Prop1 { get; set; }
public string Prop2 { get; set; }
}
I could use reflection to manually assemble/parse the list, but it will create a lot of overhead. Lots of NameValueListContent objects will be needlessly created both during the saving and the reading. Could it somehow be omitted? Especially during the reading, which is very performance-sensitive in my case.
Assume you have a AppDbContext class that holds your NameValueListContent class objects named as NVListContents. You can read and write the name-value list of objects by doing the following:
public class AppDbContext : DbContext
{
public DbSet<NameValueListContent> NVListContents { get; set; }
public AppDbContext()
: base()
{ }
}
public class SomeClass
{
private AppDbContext context { get; set; }
public SomeClass(AppDbContext _context)
{
context = _context;
}
public List<ObjectToSave> ReadObjects()
{
return context.NVListContents
.Select(nvlc => new ObjectToSave { Prop1 = nvlc.Name, Prop2 = nvlc.Value
}).ToList();
}
public bool WriteObjects(int id, string name, string value)
{
var query = context.NVListContents
.FirstOrDefault(nvlc => nvlc.Id == id);
if(query != null)
{
query.Name = name;
query.Value = value;
context.Update(query);
context.SaveChanges();
return true;
}
else
{
return false;
}
}
}
Hope, this answers to your question.

Pattern for exposing non generic and generic Class

I have implemented a common operation result for my methods and it look like this
public class OperResult
{
public string ErrorCode { get; private set; }
public string Message { get; private set; }
public object Data { get; private set; }
public bool Ok { get; private set; }
public string IncidentNumber { get; set; }
public static OperResult Success(Object data = null)
{
return new OperResult(data);
}
}
And the same operation result using generics
public class OperResult<T>
{
public string ErrorCode { get; private set; }
public string Message { get; private set; }
public T Data { get; private set; }
public bool Ok { get; private set; }
public string IncidentNumber { get; private set; }
public static OperResult<T> Success(T data = null)
{
return new OperResult<T>(data);
}
}
Is there any way to combine these two implementations and at the same time provide both Generic and non Generic version of this class?
Edit add more info about the type usage:
I want to easily create functions that return this type, for example i want to been able to create the following functions:
OperResult MakeAction()
OperResult<int> GetCount()
If I use inheritance OperResult:OperResult<Object> then OperResult.Suceess() will produce OperResult<Object> and the following will generate a compilation error:
OperResult MakeAction(){
return OperResult.Suceess(); //Cannot convert OperResult<Object> to OperResult
}
GitHub link to OperResult
As already mentioned in the comments, the non generic appears to be a OperResult<object>.
Originally went down that route but it proved to not suit the desired use case.
Switched it around to having the generic derive from the non generic and provide a new Data property.
public class OperResult {
protected OperResult(object data) {
this.Data = data;
}
public string ErrorCode { get; protected set; }
public string Message { get; protected set; }
public object Data { get; protected set; }
public bool Ok { get; protected set; }
public string IncidentNumber { get; protected set; }
public static OperResult Success(object data = null) {
return new OperResult(data ?? new object());
}
public static OperResult<T> Success<T>(T data) {
return new OperResult<T>(data);
}
}
public class OperResult<T> : OperResult {
public OperResult(T data)
: base(data) {
}
public new T Data { get; protected set; }
}
this allows the following syntax
int data = 10;
var result = OperResult.Success(data);
//result is OperResult<int>

Readonly nested object properties

I'm having a problem defining these 2 classes:
public class Article
{
public Article(long ID, string Name, ArticleFamily Family)
{
//...Initializer...
}
public ArticleFamily Family { get; set; }
//Other props...
}
public class ArticleFamily
{
public ArticleFamily(int ID, string Description)
{
//...Initializer...
}
public int ID { get; private set; }
public string Description { get; set; }
}
I have a collection of Article and each one belongs to a family.
Now, given that I have a certain ArticleFamily object I should be able to change its Description and it gets eventually persisted to a DataBase. (I left out that part for simplicity)
But I should not be able to do this:
Article art = SomeMethodReturningArticle();
art.Family.Description = "SomeOtherValue";
I should be able to change the Family of an Article entirely, replacing it with a new ArticleFamily object, but I shouldn't be able to change just the description.
Should I create a copy of the ArticleFamily class with readonly properties like this:
public class ArticleFamilyReadonly
{
ArticleFamily _family;
public ArticleFamilyReadonly(ArticleFamily Family)
{
_family = Family;
}
public int ID { get { return _family.ID; } }
//etc...
}
How can I do this in a clean way?
Here's what I threw together in LinqPad:
void Main()
{
var art = new Article(1,"2", new ArticleFamily(1, "Test"));
art.Family.Description = "What?"; // Won't work
var fam = art.Family as ArticleFamily;
fam.Description = "This works"; // This works...
}
public class Article
{
public Article(long ID, string Name, IArticleFamily Family)
{
//...Initializer...
}
public IArticleFamily Family { get; set; }
//Other props...
}
public class ArticleFamily : IArticleFamily
{
public ArticleFamily(int ID, string Description)
{
//...Initializer...
}
public int ID { get; private set; }
public string Description { get; set; }
}
public interface IArticleFamily
{
int ID { get; }
string Description { get;}
}
Cannot edit directly from the Article object unless cast to ArticleFamily object.

Exclude Single or multiple property in a C# Class

Here I have class "test".
public class test
{
public int a { get; set; }
public int b { get; set; }
public int c { get; set; }
public int d { get; set; }
}
void call1(test obj )
{
// Question: I need to exclude the property a. which means "test.a" should not able to access or view.
}
void call2(test obj )
{
// I need to exclude the property both a & b
return;
}
You can use interfaces here:
public interface IRestrictedNoAandB {
int c { get; set; }
int d { get; set; }
}
public interface IRestrictedNoA: IRestrictedNoAandB {
int b { get; set; }
}
public class test: IRestrictedNoA {
public int a { get; set; }
public int b { get; set; }
public int c { get; set; }
public int d { get; set; }
}
// You can't access property "a" within "call1" method
void call1(IRestrictedNoA obj ) {...}
// You can't access properties "a" and "b" within "call2" method
void call2(IRestrictedNoAandB obj ) {...}
you cant do this in OOP. once a property is public it will be accessible to everybody. What instead you can do is create to models like
public class test1
{
//public int a { get; set; }
public int b { get; set; }
public int c { get; set; }
public int d { get; set; }
}
public class test2
{
//public int a { get; set; }
//public int b { get; set; }
public int c { get; set; }
public int d { get; set; }
}
and use these in the two methods mentioned. Then use an object mapper like Glue or ObjectMapper to automatially map from test to test1 and test2
but using this you might have to change the structure of your program a little bit and it would be awsm if you return test1 and test2 instead of void and then change the values of the main test instance.
You can not change the structure of an object in run time.
but there are plenty of ways to prevent accessing a property of an instance, for example see this codes:
public class Test
{
// define some private varibales:
private int _a;
private int _b;
private bool accessA = true;
private bool accessB = true;
public int a
{
get
{
if (accessA)
{
return _a;
}
else
{
throw new Exception("At this moment this property was excluded.");
}
}
set
{
if (accessA)
{
_a = value;
}
else
{
throw new Exception("At this moment this property was excluded.");
}
}
}
public int b
{
get
{
if (accessB)
{
return _b;
}
else
{
throw new Exception("At this moment this property was excluded.");
}
}
set
{
if (accessB)
{
_b = value;
}
else
{
throw new Exception("At this moment this property was excluded.");
}
}
}
public int c { get; set; }
public int d { get; set; }
public void ExcludeA()
{
accessA = false;
}
public void ExcludeB()
{
accessB = false;
}
}
public void call1(Test obj)
{
//do some work here ....
obj.ExcludeA();
}
public void call2(Test obj)
{
// do some work here ...
obj.ExcludeA();
obj.ExcludeB();
}
You can try with two methods and new, you return an anonymous object which is a "partial" view of test.
public class test
{
private int a { get; set; }
private int b { get; set; }
private int c { get; set; }
private int d { get; set; }
public object testWithoutA()
{
var test = new
{
this.b,
this.c,
this.d
};
return test;
}
public object testWithoutAAndB()
{
var test = new
{
this.c,
this.d
};
return test;
}
}
UPDATE: The question concerns incoming data from WCF REST PUT
Assuming that you are working with stored procedures, why not create 2 stored procedures which ignore in one case 'a' and 'a' and 'b'?

Access Protected Members in a Subclass

Im a little stuck and after some searching i turn to you:
class StatusResponse
{
protected int _statusCode { get; set; }
protected string _statusMessage { get; set; }
public StatusResponse(string Response)
{
if (!String.IsNullOrEmpty(Response))
{
this._statusCode = int.Parse((Response.Split(' '))[0].Trim());
this._statusMessage = Response;
}
}
}
class GroupStatusResponse : StatusResponse
{
public int Count { get; private set; }
public int FirstArticle { get; private set; }
public int LastArticle { get; private set; }
public string Newsgroup { get; private set; }
public GroupStatusResponse(string Response) : base(Response)
{
string[] splitResponse = Response.Split(' ');
this.Count = int.Parse(splitResponse[1].Trim());
this.FirstArticle = int.Parse(splitResponse[2].Trim());
this.LastArticle = int.Parse(splitResponse[3].Trim());
this.Newsgroup = splitResponse[4].Trim();
}
Why cant i do this:
GroupStatusResponse resp = new GroupStatusResponse("211 1234 3000234 3002322 misc.test");
Console.Writeline(resp._statusCode);
using
Console.Writeline(resp._statusCode);
from outside the derived class is public, and not protected use.
However, you could add something like:
class GroupStatusResponse : StatusResponse
{
public int GetStatusCode()
{
return _statusCode;
}
}
which is completely valid use.
Moreover, if the scenario is that _statusCode should be allowed to read by anyone, but only the base class should be able to set it, you could change its definition to:
public string _statusMessage { get; private set; }
It's because _statusCode is protected. This means the field is inaccessible outside of the class.

Categories

Resources