Click here to Skip to main content
15,886,873 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello All,
I have a C# collection; say personal info,
List<PersonalInfo> _personalInfo =  new List<PersonalInfo>();

Currently I can perform any action on these collection using linq/lamda like
_personalInfo.Where or personalInfo.Count or _personalInfo.Select etc etc.

For security reason i am trying to restrict only specific queries on _personalInfo like Where, Take. Any other query on this list should return an error saying 'not supported'. How do i achieve this?
i am curious to know whether any way we can intercept query and check what is been used. ex:if the query is _personalInfo.Where(p=>p.age > 30) then, is there a way to know that it is a 'Where' query?


What I have tried:

I tried to intercept the query and check what is the query command but failed in doing that. Is there any method in achieving this?
Posted
Updated 29-Mar-20 20:48pm
v2

Seems, you don't understand what OriginalGriff has already told you... So, i'll try to show you an example.

Imagine, you have a Person class:
C#
public class Person
{
	private string personname = string.Empty;
	private DateTime dob = new DateTime(1900,1,1);
	
	public Person(){} //default empty constructor
	
	public Person(string _name, DateTime _dob)
	{
		personname = _name;
		dob = _dob;
	}
	
	public string Name
	{
		get => personname;
		set => personname = value;
	}
	
	public DateTime DateOfBorn
	{
		get => dob;
		set => dob = value;
	}
	
	public int Age => DateTime.Today.Year - this.dob.Year;
	
}


Now, you want to create "restricted-collection/list" of Persons. So:
C#
public class RestrictedCollection
{
	private List<Person> persons = null;

	public RestrictedCollection()
	{
		persons = new List<Person>()
		{
			new Person("Adam", new DateTime(1984,1,1)), new Person("Bart", new DateTime(1972,10,11)),
			new Person("Celine", new DateTime(1983,12,13)), new Person("Dijon", new DateTime(1986,3,17)),
			new Person("Eveline", new DateTime(1979,9,1)), new Person("Elisabeth", new DateTime(1985,5,21)),
			new Person("Ferdinand", new DateTime(1978,11,1)), new Person("Friderik", new DateTime(1979,7,31))
		};
	}
	
	public void Add(Person p)
	{
		if(!persons.Contains(p))
			persons.Add(p);
		else
			throw new InvalidOperationException($"'{p.Name}' born at {p.DateOfBorn.ToString("yyyy-MM-dd")} already exists!");
	}
	
	public void Remove(Person p)
	{
		if(persons.Contains(p))
			persons.Remove(p);
		else
			throw new InvalidOperationException($"'{p.Name}' born at {p.DateOfBorn.ToString("yyyy-MM-dd")} does not exist!");
	}
	
	public List<Person> Filter(Func<Person, bool> predicate)
	{
		List<Person> filtered = persons.Where(predicate).ToList();
		return filtered;
	}

}


Finally, the usage:
C#
void Main()
{
	RestrictedCollection rc = new RestrictedCollection();
	//find persons 
	var result = rc.Filter(x=>x.Name.StartsWith("F"));

	//add new person
	Person p = new Person("Maciej", new DateTime(1969, 12, 6));
	rc.Add(p);
	result = rc.Filter(x=>x.Name==p.Name);
	
	//try to add existing person
	rc.Add(p); //throws InvalidOperation exception!
}


Note: in above example Filter method acts like a Where generic extension of List<T>.
 
Share this answer
 
Comments
code4Better 5-Apr-20 11:26am    
Thank you very much Maciej Los. Really appreciate the detailed explanation and the time you spend for this. I have one question on above details,

From public List<person> Filter(Func<person, bool=""> predicate) method, is it possible to know 'StartsWith' is the actual query what is been called? I tried different options and i am able to get class name as 'person' and argument as 'x' but could not find any option which will give query 'StartsWith'. Can you please help me on this?
Maciej Los 5-Apr-20 12:57pm    
Sorry, i don't get you... Filter method has been created for an example only.
If you would like to expose StartsWith method, you can do it! You can expose any other method also, such as Select, Where, etc. Then, you'll be for 100% sure what method has been called. You can remove Filter generic method.

Remember, that you can change RestrictedCollection class to your needs.
code4Better 6-Apr-20 3:03am    
Sorry if i confused you. Basically what my question was
here I am calling SomeMethod() multiple ways as shown

1. rc.SomeMethod(x=>x.Name.StartsWith("F"));
2. rc.SomeMethod(x => x.Name.Equals("Cindrella"));
3. rc.SomeMethod(x => x.Name.Any());

// SomeMethod implemenation. Method checks whether query executed is approved query or not
private bool SomeMethod (Func<person, bool=""> predicate)
{
//if query matches with StartsWith, return true

{logic to identify query is StartWith}

//if query matches with Equal, return false

{logic to identify query is Equal}

//if query matches with Any, return false

{logic to identify query is Any}

.... So on
}

So here i wnat to use a method which will restrict some of the queries and will allow few of them depending upon the approved query list. In the above example i allowing only 'StartsWith' as approved query. Remaining are not approved. Hope i am able to explain better this time.
Maciej Los 6-Apr-20 3:49am    
As i told you, you have to provide StartsWith, Equals, etc. methods, instead of using one generic method (in your case it's SomeMethod). There's no other way to achieve that, unless you provide generic method in which you will pass the name of method to call.
See: How to use expression trees to build dynamic queries (C#) | Microsoft Docs[^]
code4Better 6-Apr-20 4:08am    
Thank you very much Maciej.
The best way to do that is encapsulation: make the List a private member of a class of your own, and create methods to allow users to do "permitted" actions. At no time does the encapsulating class return the encapsulated collection to the outside world, so all interaction can be controlled by you.
 
Share this answer
 
Comments
code4Better 29-Mar-20 7:04am    
Thank you @OriginalGriff. I agree with exposing methods but i am curious to know whether any way we can intercept query and check what is been used. ex:if the query is _personalInfo.Where(p=>p.age > 30) then, is there a way to know that it is a 'Where' query?
Maciej Los 29-Mar-20 9:51am    
5ed!
code4Better 29-Mar-20 10:41am    
??

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900