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'?
Related
I'm sure someone has tried to do something like this before, but I'm unsure if what I'm finding in my searches fits what I'm trying to do.
In my .Net 6 Web API I have a class to get data passed by the request:
public abstract class QueryStringParameters {
private readonly int _maxPageSize = Constants.DefaultPageSizeMax;
private int _pageSize = Constants.DefaultPageSize;
public int? PageNumber { get; set; } = 1;
public int? PageSize {
get => _pageSize;
set => _pageSize = value > _maxPageSize ? _maxPageSize : value ?? Constants.DefaultPageSize;
}
public string OrderBy { get; set; }
public string Fields { get; set; }
}
For each controller I create a view model which inherits from this:
public class ProgramParameters : QueryStringParameters {
public bool MapDepartment { get; set; } = true;
public bool MapAnother1 { get; set; } = true;
public bool MapAnother2 { get; set; } = true;
...
public ProgramParameters() {
// Default OrderBy
OrderBy = "Id";
}
}
This works fine when calling an endpoint expecting multiple results and single results. However, I want to split the QueryStringParameters properties that are for pagination, something like this:
public abstract class QueryStringParameters {
public string Fields { get; set; }
}
public abstract class QueryStringParametersPaginated : QueryStringParameters {
private readonly int _maxPageSize = Constants.DefaultPageSizeMax;
private int _pageSize = Constants.DefaultPageSize;
public int? PageNumber { get; set; } = 1;
public int? PageSize {
get => _pageSize;
set => _pageSize = value > _maxPageSize ? _maxPageSize : value ?? Constants.DefaultPageSize;
}
public string OrderBy { get; set; }
}
The problem is that then my view modal looks like this:
public class ProgramParameters : QueryStringParameters {
public bool MapDepartment { get; set; } = true;
public bool MapAnother1 { get; set; } = true;
public bool MapAnother2 { get; set; } = true;
...
public ProgramParameters() {
}
}
public class ProgramParametersPaginated : QueryStringParametersPaginated {
public bool MapDepartment { get; set; } = true; // repeated
public bool MapAnother1 { get; set; } = true; // repeated
public bool MapAnother2 { get; set; } = true; // repeated
...
public ProgramParameters() {
// Default OrderBy
OrderBy = "Id";
}
}
How can I rewrite this so that ProgramParameters and ProgramParametersPaginated don't have to have the same properties (MapDepartment, MapAnother1, MapAnother2) defined in both?
I tried something like this but that's not allowed and I am unsure how to proceed.
public class ProgramParametersPaginated : ProgramParameters, QueryStringParametersPaginated {
public ProgramParametersPaginated() {
// Default OrderBy
OrderBy = "Id";
}
}
If I understood correctly, you need to extract interfaces instead of using classes as you did, so you can apply multiple implementation.
First define the interfaces and constants for you filter properties:
public enum Constants
{
DefaultPageSizeMax = 500,
DefaultPageSize = 100
}
public interface IQueryStringParameters
{
string Fields { get; set; }
}
public interface IQueryStringParametersPaginated : IQueryStringParameters
{
string OrderBy { get; set; }
int PageSize { get; set; }
int MaxPageSize { get; set; }
int? PageNumber { get; set; }
}
Then you create an abstract class that inherit from both interfaces defined so you can write some behaviour like you did with the setters and getters:
public abstract class BaseProgramParameters : IQueryStringParameters, IQueryStringParametersPaginated
{
public string Fields { get; set; }
public string OrderBy { get; set; }
private int _pageSize = (int)Constants.DefaultPageSize;
private int _maxPageSize = (int)Constants.DefaultPageSizeMax;
public int PageSize
{
get => _pageSize;
set => _pageSize = value > _maxPageSize ? _maxPageSize : value;
}
public int MaxPageSize { get; set; }
public int? PageNumber { get; set; }
public bool MapDepartment { get; set; } = true;
public bool MapAnother1 { get; set; } = true;
public bool MapAnother2 { get; set; } = true;
public BaseProgramParameters()
{
}
public BaseProgramParameters(string orderBy)
{
this.OrderBy = orderBy;
}
}
Since you may want to define a different value on MapDeparment, MapAnother, etc, you can use the constructor on the child classes:
public class ProgramParametersPaginated : BaseProgramParameters
{
public ProgramParametersPaginated() : base("Id")
{
}
}
public class ProgramParameters : BaseProgramParameters
{
public ProgramParameters()
{
this.MapAnother1 = false;
}
}
Let me know if you have any further doubts.
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).
I am trying to create an immutable struct. The problem is, it contains mutable objects inside. Is it possible to make those immutable (without modifying their class)? For example (https://dotnetfiddle.net/KTiTzB):
public class IntHolder
{
public int X
{
get;
set;
}
}
public struct ImmutableStruct
{
public int ImmutableInt
{
get;
private set;
}
public IntHolder MyIntHolder
{
get;
private set;
}
public ImmutableStruct(int immutableInt, IntHolder myIntHolder): this ()
{
ImmutableInt = immutableInt;
MyIntHolder = myIntHolder;
}
}
public class Program
{
public static void Main()
{
Console.WriteLine("Immutability");
IntHolder intHolder = new IntHolder();
intHolder.X = 40;
Console.WriteLine(intHolder.X == 40); // TRUE
ImmutableStruct immStruct = new ImmutableStruct(10, intHolder);
Console.WriteLine(immStruct.ImmutableInt == 10); // TRUE
// immStruct.ImmutableInt = 4; // THIS DOESN'T WORK, AS EXPECTED. Hurray!
// immStruct.MyIntHolder = new IntHolder(3); // ALSO DOESN'T WORK, GOOD!
immStruct.MyIntHolder.X = 4; // how can I prevent this from working?
}
}
Is there a way to make the IntHolder member immutable while leaving the IntHolder class unmodified?
It's actually a big question: how to handle nested objects in immutable data?
https://softwareengineering.stackexchange.com/questions/279580/how-to-make-complex-objects-immutable
https://medium.freecodecamp.org/handling-state-in-react-four-immutable-approaches-to-consider-d1f5c00249d5
https://redux.js.org/recipes/structuringreducers/immutableupdatepatterns
In my opinion, It's worthy to create immutable children models to make sure the whole object immutable.
See comments in code below:
public class IntHolder
{
public int X
{
get;
set;
}
public ImmutableIntHolder ToImmutable()//convert itself to ImmutableIntHolder
{
return new ImmutableIntHolder(X);
}
}
public class ImmutableIntHolder
{
public ImmutableIntHolder(int x)
{
X = x;
}
public int X
{
get;
private set;
}
public IntHolder ToIntHolder() //convert it back to mutable IntHolder
{
return new IntHolder()
{
X = this.X
};
}
}
public struct ImmutableStruct
{
public int ImmutableInt
{
get;
private set;
}
public ImmutableIntHolder IntHolder //use ImmutableIntHolder instead
{
get;
private set;
}
public ImmutableStruct(int immutableInt, IntHolder myIntHolder) : this()
{
ImmutableInt = immutableInt;
IntHolder = myIntHolder.ToImmutable(); // convert to immutable
}
}
another option is:
public class IntHolder
{
public int X
{
get;
set;
}
}
public class ImmutableStruct //changed to class
{
public int ImmutableInt
{
get;
private set;
}
public ImmutableIntHolder IntHolder
{
get;
private set;
}
public ImmutableStruct(int immutableInt, IntHolder myIntHolder) //: this()
{
ImmutableInt = immutableInt;
IntHolder = new ImmutableIntHolder(myIntHolder); // convert here.
}
public class ImmutableIntHolder
{
public ImmutableIntHolder(IntHolder intHolder)
{
//map all properties
X = intHolder.X;
}
public int X
{
get;
private set;
}
}
}
I was just wondering if i should use custom setters in EF Core models. Consider this very simple example:
using System;
namespace EFTest.Models
{
public class Reservation
{
public int ReservationId { get; set; }
public DateTime Start { get; set; }
public DateTime End { get; set; }
public int ResourceId { get; set; }
public int CustomerId { get; set; }
public Customer Customer { get; set; }
public Resource Resource { get; set; }
}
public class Resource
{
public int ResourceId { get; set; }
public string Name { get; set; }
}
public class Customer
{
public int CustomerId { get; set; }
public string Name { get; set; }
}
}
The issue being that when i have to save a model, and add an instance of a class to it, it handles getting the foreign key from said added instance just fine, like so:
public void SaveReservation()
{
var db = new Datebase();
var reservation = new Reservation(){ Start = new DateTime().Now, End = new DateTime().Now.AddDays(7)};
reservation.Resource = db.Resources.Find(2);
reservation.Customer = db.Customers.Find(4);
db.Reservations.Add(reservation);
db.SaveChanges();
}
but if i set the foreign key property for customer, but then add the instance of a resource, forexample, it is utterly unable to handle getting the foreignkey, like so:
public void SaveReservation()
{
var db = new Datebase();
var reservation = new Reservation(){ Start = new DateTime().Now, End = new DateTime().Now.AddDays(7)};
reservation.Resource = db.Resources.Find(2);
reservation.CustomerId = 4;
db.Reservations.Add(reservation);
db.SaveChanges();
}
Resulting in a sqlite exception 19, 'failing to get foreignkey' or somesuch.
The only solution i can think of is to do custom setters and getters to handle setting the property based on the key, and vice versa, e.g.:
using System;
namespace EFTest.Models
{
public class Reservation
{
public int ReservationId { get; set; }
public DateTime Start { get; set; }
public DateTime End { get; set; }
public int ResourceId
{
get
{
if(_Resource != null)
{
return _Resource.ResourceId;
}
else
{
return 0;
}
}
set
{
if(_Resource != null && !_Resource.ResourceId.Equals(value))
{
_Resource = null;
}
}
}
public int CustomerId
{
get
{
if(_Customer != null)
{
return _Customer.CustomerId;
}
else
{
return 0;
}
}
set
{
if(_Customer != null && !_Customer.CustomerId.Equals(value))
{
_Customer = null;
}
}
}
public Customer Customer
{
get
{
return _Customer;
}
set
{
_Customer = value;
if(value != null)
{
CustomerId = _Customer.CustomerId;
}
else
{
CustomerId = 0;
}
}
}
private Customer _Customer { get; set; }
public Resource Resource
{
get
{
return _Resource;
}
set
{
_Resource = value;
if(value != null)
{
ResourceId = _Resource.ResourceId;
}
else
{
ResourceId = 0;
}
}
}
private Resource _Resource { get; set; }
}
public class Resource
{
public int ResourceId { get; set; }
public string Name { get; set; }
}
public class Customer
{
public int CustomerId { get; set; }
public string Name { get; set; }
}
}
But I am not at all certain this is a good way to handle the issue, can someone provide some insight on whether it is a good way to handle it? and whether there is a better one?
thank you.
A thank you to DevilSuichiro for providing the very clear and useful answer:
"But no, you shouldn't use custom getters or setters in your BO's, those should reflect your db schema pretty neatly."
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.