Can I set the property of a struct using Expressions? - c#

I have the following method which sets the value for the given PropertyInfo on the given TInstance. This is to avoid the inefficiency of reflection.
public static Action<TInstance, object> CreateSetter<TInstance>(PropertyInfo propertyInfo, bool includeNonPublic = false)
{
var setMethod = propertyInfo.GetSetMethod(includeNonPublic);
var instance = Expression.Parameter(typeof(TInstance), "instance");
var value = Expression.Parameter(typeof(object), "value");
var valueCast = !propertyInfo.PropertyType.IsValueType
? Expression.TypeAs(value, propertyInfo.PropertyType)
: Expression.Convert(value, propertyInfo.PropertyType);
return Expression.Lambda<Action<TInstance, object>>(
Expression.Call(instance, setMethod, valueCast), instance, value).Compile();
}
So given the following model:
public sealed class PersonClass
{
public string Name {get; set;}
}
I can set the Name using:
var person = new PersonClass();
var nameProp = person.GetType().GetProperties().Where(p => p.Name == "Name").First();
var nameSetter = CreateSetter<PersonClass>(nameProp);
nameSetter(person, "Foo");
This is all good however if I try the method with a struct e.g.:
public struct PersonStruct
{
public string Name {get; set;}
}
The name is always null. I suspect boxing/unboxing is biting me somehow.
In fact if I use FastMember the same behavior exhibits when using:
PersonStruct person = new PersonStruct();
var accessor = TypeAccessor.Create(person.GetType());
accessor[person, "Name"] = "Foo";
However when I box the person as object then FastMember is able to set the value correctly:
object person = new PersonStruct();
var accessor = TypeAccessor.Create(person.GetType());
accessor[person, "Name"] = "Foo";
Any ideas how I can handle this boxing inside the CreateSetter for when TInstance is a value type?

You need an expression that creates a delegate that takes a by-ref argument, so that it will affect the struct passed, rather than a copy. E.g.:
public struct PersonStruct
{
public string Name {get; set;}
}
delegate void FirstByRefAction<T1, T2>(ref T1 arg1, T2 arg2);
void Main()
{
ParameterExpression par1 = Expression.Parameter(typeof(PersonStruct).MakeByRefType());
ParameterExpression par2 = Expression.Parameter(typeof(string));
FirstByRefAction<PersonStruct, string> setter = Expression.Lambda<FirstByRefAction<PersonStruct, string>>(
Expression.Assign(Expression.Property(par1, "Name"), par2),
par1, par2
).Compile();
PersonStruct testStruct = new PersonStruct();
setter(ref testStruct, "Test Name");
Console.Write(testStruct.Name); // outputs "Test Name"
}
This is to avoid the inefficiency of reflection.
Note that the method- and property-calling expression types largely use reflection internally. In the case of interpreted expressions, they do so with each call, in the case of IL-compiled expressions reflection is still used in the compilation step.

As noted in the comments, you really shouldn't create mutable structs. However, to answer the question, structs are value types and therefore a copy of your struct is passed to the Action and therefore the original person value is not changed.
You need a way to pass the struct by reference. However, expressions do not support creating "methods" that take parameters by reference.
What you can do is use the DynamicMethod class to do something like this:
public delegate void StructSetter<TInstance>(ref TInstance instance, object value) where TInstance : struct;
public StructSetter<TInstance> CreateSetter<TInstance>(
PropertyInfo propertyInfo,
bool includeNonPublic = false) where TInstance : struct
{
DynamicMethod method =
new DynamicMethod(
"Set",
typeof(void),
new [] { typeof(TInstance).MakeByRefType(), typeof(object )},
this.GetType());
var generator = method.GetILGenerator();
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldarg_1);
generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod(includeNonPublic));
generator.Emit(OpCodes.Ret);
return (StructSetter<TInstance>)method.CreateDelegate(typeof (StructSetter<TInstance> ));
}
We had to create a StructSetter delegate because the standard Action delegates do not support passing by reference.
Don't forget to cache the delegate or otherwise the cost of compiling is going to slow down your application.

Related

How can I create a delegate to read a property of an anonymous type?

I have a method that is called with an instance of an anonymous type. The type is always the same, but the instance is different.
NOTE: I am passed the anonymous object simply as a type object.
I know the anonymous type has a property named Request of type HttpRequestMessage. Here is my method that is executed with the anonymous type in info.Value.
void IObserver<KeyValuePair<string, object> event> OnNext(KeyValuePair<string, object> info)
{
HttpRequestMessage request = ?????
}
I can get the property getter like so:
MethodInfo propertyGetter = type.GetProperty("Request").GetGetMethod();
But I can't afford the cost of reflection when reading the property of the instance passed to me.
How can I create a delegate that I pass the instance to and get the property value?
I tried this
private delegate HttpRequestMessage RequestPropertyGetterDelegate(object instance);
private static RequestPropertyGetterDelegate RequestPropertyGetter;
private static RequestPropertyGetterDelegate CreateRequestFromPropertyDelegate(Type type)
{
MethodInfo propertyGetter = type.GetProperty("Request").GetGetMethod();
return (RequestPropertyGetterDelegate)Delegate.CreateDelegate(typeof(RequestPropertyGetterDelegate), propertyGetter);
}
But I am experiencing a binding error
System.ArgumentException: 'Cannot bind to the target method because its signature is not compatible with that of the delegate type.'
Here it is, using expression trees.
All you have to do is cache the getter, the performance should be the same as direct access.
void Main()
{
var instance = new TestClass { Request = "Something 2" };
var getter = CreateRequestFromPropertyDelegate(typeof(TestClass));
// Cache getter per type
var value = getter(instance);
Console.WriteLine(value); // Prints "Something 2"
}
private delegate string RequestPropertyGetterDelegate(object instance);
static RequestPropertyGetterDelegate CreateRequestFromPropertyDelegate(Type type)
{
// Entry of the delegate
var instanceParam = Expression.Parameter(typeof(object), "instance");
// Cast the instance from "object" to the correct type
var instanceExpr = Expression.TypeAs(instanceParam, type);
// Get the property's value
var property = type.GetProperty("Request");
var propertyExpr = Expression.Property(instanceExpr, property);
// Create delegate
var lambda = Expression.Lambda<RequestPropertyGetterDelegate>(propertyExpr, instanceParam);
return lambda.Compile();
}
class TestClass
{
// Using string here because I'm on LINQPad
public string Request { get; set; }
}
Using some expression trees it should be:
private static readonly ConcurrentDictionary<Type, Func<object, string>> extractorsCache = new ConcurrentDictionary<Type, Func<object, string>>();
public static string GetRequest(object obj)
{
Type type = obj.GetType();
Func<object, string> extractor = extractorsCache.GetOrAdd(type, BuildExtractor);
string res = extractor(obj);
return res;
}
public static Func<object, string> BuildExtractor(Type type)
{
var par = Expression.Parameter(typeof(object));
var prop = Expression.Property(Expression.TypeAs(par, type), "Request");
return Expression.Lambda<Func<object, string>>(prop, par).Compile();
}
and then:
string r1 = GetRequest(new { Request = "Foo" });
string r2 = GetRequest(new { Request = "Bar" });
string r3 = GetRequest(new { Request = "Baz" });
string r4 = GetRequest(new { Request = "Zoo", Ix = 1 });
Note that the compiled expression trees are cached in a ConcurrentDictionary<,>, so these four GetRequest will generate two compiled expressions (because in the end there are two anonymous types here).
There is no way to do this without Genric-ising the function you are writing it in. Because the anonymous type is more specific than object, an object parameter will never bind.
You can work around this by putting the whole thing in a static generic class:
static class AnonHelper<T>
{
public readonly Func<T, HttpRequestMessage> Getter = (Func<T, HttpRequestMessage>)
Delegate.CreateDelegate(
typeof(Func<T, HttpRequestMessage>, propertyGetter)),
typeof(T)
.GetProperty("Request")
.GetGetMethod()
);
}
You still cannot access it as you cannot declare the generic parameter.
So wrap it in a function on the outside (you could even make it an extension):
HttpRequestMessage GetProp<T>(T obj)
{
return AnonHelper<T>.Getter(obj);
}
You can then call it like so:
GetProp(anonObj)
This only works if you can call GetProp at the point where the type of the anonymous object is statically known, usually the same method it is declared in.

C# - How to access instances of a particular type that are used in Func<int> delegate

In Factory.Process(..) method, I want get hold of instances of MyClass that are being used in the lambda expression of the Func delegate. But, How?
Can someone help me find a way to do it.
Edit: This is an artificial example that demonstates my need. My intention behind this approach is that, I want to keep track of (or subscribe to) all the MyClass objects that are used in the delegate definition. So that, I can recalculate my total value whenever any MyClass object value is changed. Please suggest as to how to go about to solve this.
Note: Expression tree doesnt seem to help in my case because I cant modify my parameter type at this moment and it restricts the usage of my complex function definitions.
public class MyClass
{
public int Value;
public MyClass(int value)
{
Value = value;
}
}
public class TestClass
{
public void TestMethod()
{
var obj1 = new MyClass(10);
var obj2 = new MyClass(20);
Factory.Process(() => obj1.Value + obj2.Value);
}
}
public static class Factory
{
public static void Process(Func<int> function)
{
var total = function.Invoke();
// Here, apart from invoke, I want to access the all the instances of MyClass that are used in 'function'
// but how do I get to obj1 and obj2 objects through the 'function' delegate?
}
}
First of all, if you type an input parameter as just Func<T> it's not an expression, but just a lambda syntax for delegates.
If you want to be able to access the expression and do some reflection and/or analysis, you need to type your parameters as Expression<T>. For example: Expression<Func<int>>. This turns your expression into an expression tree.
Expression trees enable you to access the expression like a data structure. Once you've finished analyzing your expression tree, you can call yourExpression.Compile(), and this will compile your expression tree into a delegate that can be invoked as any other delegate (either named and anonymous ones).
For example, obj1 would be accessed this way:
public class MyClass
{
public int Value { get; set; }
}
static void Main(string[] args)
{
var obj1 = new MyClass { Value = 1 };
var obj2 = new MyClass { Value = 2 };
Expression<Func<int>> expr = () => obj1.Value + obj2.Value;
BinaryExpression binaryExpr = (BinaryExpression)expr.Body;
MemberExpression memberExpr = (MemberExpression)binaryExpr.Left;
MemberExpression fieldExpr = (MemberExpression)memberExpr.Expression;
ConstantExpression constantExpr = (ConstantExpression)fieldExpr.Expression;
dynamic value = constantExpr.Value;
MyClass some = value.obj1;
}
Update
OP said in some comment:
unfortunately, changing from parameter Func to
Expression> doesnt seem to work well in my situation because,
expression tree is restricting my function delegate definition from
using assignment operators and statement body.
My answer to this is you want an unexisting universal solution, because any other solution might compromise maintainability.
Maybe there's an alternative that will allow you to stay with delegates instead of expression trees: a delegate with an out parameter which would contain a collection of objects involved in there...
Since standard BCL Func delegates don't come with output parameters, you can declare your own Func delegate as follows:
public delegate TResult Func<out T>(out IDictionary<string, object> objects);
...and your delegate should set the so-called out parameter:
using System;
using System.Collections.Generic;
public class Program
{
public class MyClass
{
public int Value { get; set; }
}
public delegate void Func<out T>(out IDictionary<string, object> objects);
public static void Main()
{
Func<int> someFunc = (out IDictionary<string, object> objects) =>
{
var obj1 = new MyClass { Value = 1 };
var obj2 = new MyClass { Value = 2 };
int result = obj1.Value + obj2.Value;
objects = new Dictionary<string, object> { { "obj1", obj1 }, { "obj2", obj2 } };
};
IDictionary<string, object> objectsInFunc;
someFunc(out objectsInFunc);
}
}
As written, it cannot be done, because you're trying to access information about the exact code and would thus need to examine the incoming IL (since the actual C# code is gone after compilation).
However, it WOULD be possible using the metacode libraries of System.Linq.Expression namespace, but only if you swap out Func<int> for Expression<Func<int>>. With this, you would then be able to walk the expressions tree created by your lambda call. Using an Expression in place of another delegate type also tells the compiler to make an expression tree, rather than actually compiling the code, so this won't work if you pass a direct method or try to examine non-expression tree objects the same way.
You can if you change the parameter type of Process to Expression<Func<int>> expr:
public static void Process(Expression<Func<int>> expr)
{
Func<int> function = expr.Compile();
var total = function();
Expression left = ((BinaryExpression)expr.Body).Left;
Expression leftObjExpr = ((MemberExpression)left).Expression;
Expression<Func<MyClass>> leftLambda =
Expression.Lambda<Func<MyClass>>(leftObjExpr);
Func<MyClass> leftFunc = leftLambda.Compile();
MyClass obj1 = leftFunc();
int value = obj1.Value; // ==> 10
// Same with right operand...
}
Note that you can still invoke the function; you just have to compile the lambda expression to get a callable function.
However, this will only work with a binary expression. If you want to parse all kinds of expressions, this becomes quite complicated. You best solve this problem with the Visitor pattern.

How to combine MemberExpression instances in C# for a LambdaExpression?

Given a class like this:
public class AnEntity
{
public int prop1 { get; set; }
public string prop2 { get; set; }
public string prop3 { get; set; }
}
I am able to generate a lambda expression that selects one property like this:
ParameterExpression pe = Expression.Parameter(typeof(AnEntity), "x");
MemberExpression selectClause = Expression
.MakeMemberExpression(
pe,
typeof(AnEntity).GetProperty(prop2)); // selecting prop2
var selectLambda = Expression.Lambda<Func<AnEntity, object>>(selectClause, pe);
I can then use the lambda expression like this:
IQueryable<AnEntity> myEntities = dbContext.MyEntities.AsQueryable();
var results = myEntities.Select(selectLambda);
How can I add a second select clause to the selectLambda? For example, how would I select both prop2 and prop3?
Below is a fleshed out example of what "usr" described in his solution using MemberInitExpression.
For my solution, I am going to provide you with a new class that you will want write the expression result into. In reality, this could be the POCO for the entity itself, but by specifying a different class, it is clearer which class is the class you are projecting into as compared to the class you are projecting from. As "usr" mentioned, you can also try to use Tuple or other constructs. My current favorite is to use the extra code I appended to the bottom to create a new type dynamically. This is a bit more flexible than Tuple, but it has some disadvantages in that it requires Reflection to access it for the most part.
Class to project into:
public class Holder
{
public int Item1{ get; set; }
public string Item2 { get; set; }
public string Item3 { get; set; }
}
Code to create expression:
ParameterExpression paramExp = Expression.Parameter(typeof(AnEntity));
NewExpression newHolder = Expression.New(typeof(Holder));
Type anonType = typeof(Holder);
MemberInfo item1Member = anonType.GetMember("Item1")[0];
MemberInfo item2Member = anonType.GetMember("Item2")[0];
MemberInfo item3Member = anonType.GetMember("Item3")[0];
// Create a MemberBinding object for each member
// that you want to initialize.
MemberBinding item1MemberBinding =
Expression.Bind(
item1Member,
Expression.PropertyOrField(paramExp, "prop1"));
MemberBinding item2MemberBinding =
Expression.Bind(
item2Member,
Expression.PropertyOrField(paramExp, "prop2"));
MemberBinding item3MemberBinding =
Expression.Bind(
item3Member,
Expression.PropertyOrField(paramExp, "prop3"));
// Create a MemberInitExpression that represents initializing
// two members of the 'Animal' class.
MemberInitExpression memberInitExpression =
Expression.MemberInit(
newHolder,
item1MemberBinding,
item2MemberBinding,
item3MemberBinding);
var lambda = Expression.Lambda<Func<AnEntity, Holder>>(memberInitExpression, paramExp);
Finally, how you would call the expression:
IQueryable<AnEntity> myEntities = dbContext.MyEntities.AsQueryable();
var results = myEntities.Select(selectLambda);
Here is some additional code if you wanted to define a type dynamically for the return value:
public static Type CreateNewType(string assemblyName, string typeName, params Type[] types)
{
// Let's start by creating a new assembly
AssemblyName dynamicAssemblyName = new AssemblyName(assemblyName);
AssemblyBuilder dynamicAssembly = AssemblyBuilder.DefineDynamicAssembly(dynamicAssemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder dynamicModule = dynamicAssembly.DefineDynamicModule(assemblyName);
// Now let's build a new type
TypeBuilder dynamicAnonymousType = dynamicModule.DefineType(typeName, TypeAttributes.Public);
// Let's add some fields to the type.
int itemNo = 1;
foreach (Type type in types)
{
dynamicAnonymousType.DefineField("Item" + itemNo++, type, FieldAttributes.Public);
}
// Return the type to the caller
return dynamicAnonymousType.CreateType();
}
The way to answer questions like these is to write the pattern you want to build in strongly typed C# (select new { x.p1, x.p2 }) and use the debugger to look at the expression tree. Then you build that tree yourself.
What you will find is a MemberInitExpression instantiating a class with the two properties p1 and p2 that are being initialized from x.
You have to supply such a class somehow. Either define it yourself (class X { string p1, p2; }) or use a Tuple-like construct. Or an object[].
Understand that you can only have one return value. So it needs to encapsulate multiple values.
The easiest way is going to be using an object[]. Look at how the C# compiler does it.
There is no "second select return value". You get to return one value, which might be an aggregate.
The C# language provides a lot of syntactic sugar in this area, in the form of LINQ and anonymous types. To return an aggregate via a lambda built by expression trees, you'll have to create a type to hold all the different values (just like the C# compiler does behind the scenes when it sees an anonymous type) and then call its constructor passing the multiple values you want to return (this is actually somewhat easier than what C# does behind the scenes, which is call a bunch of property setters). At runtime, there are no anonymous types. They all get named, if not by the programmer then by the compiler.
In fact you can probably use a Tuple<Type1, Type2, Type3> instead of making a class especially for the purpose. But then your member properties won't be named nicely.

Given a property name, how can I create a delegate to get its value

We have some code that given a property name uses reflection to implement a Comparer.
I would like to store a delegate/Func to get the value rather than paying the reflection price each time we need to get a value.
Given a class like this:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
I tried to write a function that would create a delegate for me
Func<T, object> CreateGetFuncFor<T>(string propertyName)
{
PropertyInfo prop = typeof(T).GetProperty(propertyName);
return (Func<T, object>)Delegate.CreateDelegate(typeof(Func<T, object>),
null,
prop.GetGetMethod());
}
The following code works fine for the getting the Name
var person = new Person { Name = "Dave", Age = 42 };
var funcitonToGetName = CreateGetFuncFor<Person>("Name");
Console.WriteLine(funcitonToGetName(person));
var functionToGetAge = CreateGetFuncFor<Person>("Age");
but for the Age proerty it throws an ArgumentException with the message "Error binding to target method"
What am I missing? Is there another way to do it?
It seems odd that you know the declaring type at compile-time but not the property type. Anyway...
You'll need an extra step to convert the property value to an object so that it matches the Func<T,object> delegate's return type. (The extra step isn't strictly necessary for reference-typed properties, but doesn't do any harm.)
Func<T, object> CreateGetFuncFor<T>(string propertyName)
{
var parameter = Expression.Parameter(typeof(T), "obj");
var property = Expression.Property(parameter, propertyName);
var convert = Expression.Convert(property, typeof(object));
var lambda = Expression.Lambda(typeof(Func<T, object>), convert, parameter);
return (Func<T, object>)lambda.Compile();
}
Its probably because Age is essentially defined as:
public int Age {get; private set;}
and a method returning an int is not implicitly convertible to a method returning an object, whereas String is.
try:
Func<T, R> CreateGetFuncFor<T, R>(string propertyName)
{
PropertyInfo prop = typeof(T).GetProperty(propertyName);
return (Func<T, R>)Delegate.CreateDelegate(typeof(Func<T, R>),
null,
prop.GetGetMethod());
}
and then
var functionToGetAge = CreateGetFuncFor<Person, int>("Age");

Creating a property setter delegate

I have created methods for converting a property lambda to a delegate:
public static Delegate MakeGetter<T>(Expression<Func<T>> propertyLambda)
{
var result = Expression.Lambda(propertyLambda.Body).Compile();
return result;
}
public static Delegate MakeSetter<T>(Expression<Action<T>> propertyLambda)
{
var result = Expression.Lambda(propertyLambda.Body).Compile();
return result;
}
These work:
Delegate getter = MakeGetter(() => SomeClass.SomeProperty);
object o = getter.DynamicInvoke();
Delegate getter = MakeGetter(() => someObject.SomeProperty);
object o = getter.DynamicInvoke();
but these won't compile:
Delegate setter = MakeSetter(() => SomeClass.SomeProperty);
setter.DynamicInvoke(new object[]{propValue});
Delegate setter = MakeSetter(() => someObject.SomeProperty);
setter.DynamicInvoke(new object[]{propValue});
The MakeSetter lines fail with "The type arguments cannot be inferred from the usage. Try specifying the type arguments explicitly."
Is what I'm trying to do possible? Thanks in advance.
The Expression API supports this in .NET 4.0, but sadly the C# compiler doesn't add any extra candy to support. But the good news is that you can trivially take a "get" expression (which the C# compiler can write) and re-write it as a "set" expression.
And even better; if you don't have .NET 4.0, there are still at least two other ways of performing a "set" via an expression written as a "get".
Here they all are, for info:
using System;
using System.Linq.Expressions;
using System.Reflection;
class Foo {
public string Bar { get; set; }
static void Main() {
// take a "get" from C#
Expression<Func<Foo, string>> get = foo => foo.Bar;
// re-write in .NET 4.0 as a "set"
var member = (MemberExpression)get.Body;
var param = Expression.Parameter(typeof(string), "value");
var set = Expression.Lambda<Action<Foo, string>>(
Expression.Assign(member, param), get.Parameters[0], param);
// compile it
var action = set.Compile();
var inst = new Foo();
action(inst, "abc");
Console.WriteLine(inst.Bar); // show it working
//==== reflection
MethodInfo setMethod = ((PropertyInfo)member.Member).GetSetMethod();
setMethod.Invoke(inst, new object[] { "def" });
Console.WriteLine(inst.Bar); // show it working
//==== Delegate.CreateDelegate
action = (Action<Foo, string>)
Delegate.CreateDelegate(typeof(Action<Foo, string>), setMethod);
action(inst, "ghi");
Console.WriteLine(inst.Bar); // show it working
}
}
As per my comments - because links go dead - I have posted the full code as an answer to the question. YES it is possible to do what the OP is requesting. and here is a nice little gem from Nick demonstrating it. Nick credits this page and another page for his complete solution along with performance metrics. I provide that below instead of just a link.
// returns property getter
public static Func<TObject, TProperty> GetPropGetter<TObject, TProperty>(string propertyName)
{
ParameterExpression paramExpression = Expression.Parameter(typeof(TObject), "value");
Expression propertyGetterExpression = Expression.Property(paramExpression, propertyName);
Func<TObject, TProperty> result =
Expression.Lambda<Func<TObject, TProperty>>(propertyGetterExpression, paramExpression).Compile();
return result;
}
// returns property setter:
public static Action<TObject, TProperty> GetPropSetter<TObject, TProperty>(string propertyName)
{
ParameterExpression paramExpression = Expression.Parameter(typeof(TObject));
ParameterExpression paramExpression2 = Expression.Parameter(typeof(TProperty), propertyName);
MemberExpression propertyGetterExpression = Expression.Property(paramExpression, propertyName);
Action<TObject, TProperty> result = Expression.Lambda<Action<TObject, TProperty>>
(
Expression.Assign(propertyGetterExpression, paramExpression2), paramExpression, paramExpression2
).Compile();
return result;
}
Action<T> represents a delegate that takes one parameter of type T and returns nothing. The lambda expressions you provide to MakeSetter represent delegates that take no parameter and return either SomeClass.SomeProperty or someObject.SomeProperty.
The error messages you're getting are due to the fact that the compiler cannot infer the types from the lambda expressions you're passing into the MakeSetter method because what you've passed and what the method is expecting are not in sync.
Your MakeSetter is expecting an Action<T> and you are passing it a Func<T> (() => someObject.SomeProperty). Try the following:
Delegate setter = MakeSetter((prop) => {someObject.SomeProperty = prop;});
setter.DynamicInvoke(new object[]{propValue});
EDIT Doesn't look like you can convert statement lambdas into expressions. This is somewhat of a round about way to do it without expressions - straight to delegates:
class Test2 {
delegate void Setter<T>(T value);
public static void Test() {
var someObject = new SomeObject();
Setter<string> setter = (v) => { t.SomeProperty = v; };
setter.DynamicInvoke(new object[]{propValue});
}
}

Categories

Resources