PropertyInfo.SetValue()

  • Thread starter Thread starter FourEyes
  • Start date Start date
F

FourEyes

I've read that Reflection is slow and shouldn't be used when
performance is a concern. In my case, performance is definitely a
concern, so I was thinking that I could collect the PropertyInfo
objects that I need at initialization, and then just call
PropertyInfo.SetValue() at runtime. Can anyone tell me 1) how
expensive is the call to PropertyInfo.SetValue() ? and 2) what is a
better alternative ?

I already have a hand-made solution where delegates are stored in a
Dictionary but I am hoping that .NET has something that requires less
code, ie, is auto-generated somehow.

Thanks!
 
Well, using reflection is going to be pretty slow still. You are going
to save some overhead on looking up the PropertyInfo instances, but most of
the time is going to be wasted in calling SetValue.

You can always measure the impact yourself using the StopWatch class in
the System.Diagnostics namespace.

If the properties that you want to set the value of are public (or
available to the code that will be setting the properties), then you can
look into creating a dynamic assembly which will call the property directly,
and assign it the value you want. This would be the fastest way to assign
the value, but it will only work if you have access to the property from the
calling code (if you are trying to call a private property, for example,
then this wouldn't work).
 
2) what is a better alternative ?

Not sure if it's a better alternative for you, but there's a method that
worked out well for me. I needed to add plugin capability to an application I
built and the plugins had to be loaded via reflection at the start of the
program for later use. What I did was built an abstract base class containing
the members my app would call. The plugins then had to inherit from this
class.

When I instantiated the classes at runtime, I merely worked with them as the
base type. This let me use reflection only to instantiate the classes. All
the actual calls were handled directly via the base classes interface.

You may be able to use an interface instead of burning the base class in
your case. I needed some common functionality, though, so needed the base
class.
I am hoping that .NET has something that requires less code, ie, is auto generated somehow.

There are code generators available that may suit your needs. Most of the
generators I've seen are specific to database code, however, I think there
are more generic ones available.

You could also build your own. It wouldn't be too much trouble to build a
program that uses reflection to query the class structures and generate code
to do what you need explicitly.
 
Well, using reflection is going to be pretty slow still. You are going
to save some overhead on looking up the PropertyInfo instances, but most of
the time is going to be wasted in calling SetValue.

You can always measure the impact yourself using the StopWatch class in
the System.Diagnostics namespace.

If the properties that you want to set the value of are public (or
available to the code that will be setting the properties), then you can
look into creating a dynamic assembly which will call the property directly,
and assign it the value you want. This would be the fastest way to assign
the value, but it will only work if you have access to the property from the
calling code (if you are trying to call a private property, for example,
then this wouldn't work).

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)




I've read that Reflection is slow and shouldn't be used when
performance is a concern. In my case, performance is definitely a
concern, so I was thinking that I could collect the PropertyInfo
objects that I need at initialization, and then just call
PropertyInfo.SetValue() at runtime. Can anyone tell me 1) how
expensive is the call to PropertyInfo.SetValue() ? and 2) what is a
better alternative ?
I already have a hand-made solution where delegates are stored in a
Dictionary but I am hoping that .NET has something that requires less
code, ie, is auto-generated somehow.
Thanks!- Masquer le texte des messages précédents -

- Afficher le texte des messages précédents -

Yeah, I haven't got around to timing the SetValue calls yet. I am
rather hesitant to create a dynamic assembly for this solution because
it sounds complicated. I need to be able to easily add classes to the
solution, so I don't want to have anything complicated involved in the
build process or in the code.

However, the solution that I am trying out right now is also more
complicated than I like, because it requires the developers to create
delegates to set/get each field and then to store these into a
dictionary.

Do you think that using dynamic assemblies would be simpler and re-
usable than my method of handwriting delegates for each property and
manually stuffing them into a Dictionary ?

Thanks again!
N
 
Do you think that using dynamic assemblies would be simpler and re-
usable than my method of handwriting delegates for each property and
manually stuffing them into a Dictionary ?

Using dynamic assembly is only way to add and access properties fast. Is is
very easy.

Example:

using System;
using System.Windows.Forms;
using System.Reflection;
using System.CodeDom.Compiler;

class Program {

static void Main(string[] args) {
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
......
}

static Assembly CurrentDomain_AssemblyResolve(object sender,
ResolveEventArgs args) {

if (!args.Name.StartsWith("EntityExtension") ) {
return null;
}
return CreateAssembly();
}

static Assembly CreateAssembly() {

CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
CompilerParameters compilerParameters = new CompilerParameters();
compilerParameters.GenerateInMemory = true;
compilerParameters.ReferencedAssemblies.Add("EntityBase.dll");
compilerParameters.ReferencedAssemblies.Add("System.dll");

CompilerResults compilerResults =
provider.CompileAssemblyFromSource(compilerParameters,
@"
using System;

public class Customer : EntityBase.CustomerWithStandardProperties {

protected string _a_a;

// sample dynamic property
public string A_a {
get { return _a_a; }
set { _a_a = value; }
}}
");

return compilerResults.CompiledAssembly;
}

}
}
 
Hmmm... I would like to do something like
ClassA objA = new ClassA();

foreach( KeyValuePair<propertyName,propertyValue> in
newPropertyValues )
{
objA.SetProperty(propertyName, propertyValue);
}
How would I use a dynamic assembly to do something like that ?

Thanks again,
N
 
I've read that Reflection is slow and shouldn't be used when
performance is a concern. In my case, performance is definitely a
concern

To what extent? Have you got some concrete goals in mind? Using
reflection is slower than not using reflection, but that doesn't mean
it's necessarily *too* slow.

Unless you've got a test bed which measures performance and some
targets, it will be hard to know when you've got a solution which is
deemed acceptable.

Jon
 
To what extent? Have you got some concrete goals in mind? Using
reflection is slower than not using reflection, but that doesn't mean
it's necessarily *too* slow.

Unless you've got a test bed which measures performance and some
targets, it will be hard to know when you've got a solution which is
deemed acceptable.

Jon
Jon,

We have an old version of the product which is taking a lot of time to
complete, for various reasons. I can see now that for the case of
creating 66K objects with about 20 properties that need to be set, it
is quite slow. I will of course time the process with and without
using PropertyInfo.SetValue(), but I would like to get better
performance without the maintenance cost of a complex solution.

Thanks,
Nora
 
Norapinephrine said:
We have an old version of the product which is taking a lot of time to
complete, for various reasons. I can see now that for the case of
creating 66K objects with about 20 properties that need to be set, it
is quite slow. I will of course time the process with and without
using PropertyInfo.SetValue(), but I would like to get better
performance without the maintenance cost of a complex solution.

How slow is it? On my laptop, I can do that in just over 7 seconds
(code below - I've used C# 3 for automatic properties, but that's all).

How often are you doing this?

Using PropertyDescriptor instead of PropertyInfo gives me about the
same performance.

If this isn't good enough, see whether Marc Gravell's
"HyperDescriptor" code helps you:

http://www.codeproject.com/csharp/HyperPropertyDescriptor.asp



using System;
using System.Diagnostics;
using System.Reflection;
using System.Collections.Generic;

public class LotsOfProperties
{
public string Foo0 { get; set; }
public string Foo1 { get; set; }
public string Foo2 { get; set; }
public string Foo3 { get; set; }
public string Foo4 { get; set; }
public string Foo5 { get; set; }
public string Foo6 { get; set; }
public string Foo7 { get; set; }
public string Foo8 { get; set; }
public string Foo9 { get; set; }
public string Foo10 { get; set; }
public string Foo11 { get; set; }
public string Foo12 { get; set; }
public string Foo13 { get; set; }
public string Foo14 { get; set; }
public string Foo15 { get; set; }
public string Foo16 { get; set; }
public string Foo17 { get; set; }
public string Foo18 { get; set; }
public string Foo19 { get; set; }
}

public class Test
{
static void Main()
{
List<PropertyInfo> properties = new List<PropertyInfo>();
for (int i=0; i < 20; i++)
{
properties.Add(typeof(LotsOfProperties).
GetProperty("Foo"+i));
}

Stopwatch sw = Stopwatch.StartNew();
for (int i=0; i < 66000; i++)
{
object o = Activator.CreateInstance
(typeof(LotsOfProperties));
foreach (PropertyInfo prop in properties)
{
prop.SetValue(o, "Value", null);
}
}
sw.Stop();
Console.WriteLine (sw.ElapsedMilliseconds);
}
}
 
How slow is it? On my laptop, I can do that in just over 7 seconds
(code below - I've used C# 3 for automatic properties, but that's all).

How often are you doing this?

Using PropertyDescriptor instead of PropertyInfo gives me about the
same performance.

If this isn't good enough, see whether Marc Gravell's
"HyperDescriptor" code helps you:

http://www.codeproject.com/csharp/HyperPropertyDescriptor.asp

using System;
using System.Diagnostics;
using System.Reflection;
using System.Collections.Generic;

public class LotsOfProperties
{
public string Foo0 { get; set; }
public string Foo1 { get; set; }
public string Foo2 { get; set; }
public string Foo3 { get; set; }
public string Foo4 { get; set; }
public string Foo5 { get; set; }
public string Foo6 { get; set; }
public string Foo7 { get; set; }
public string Foo8 { get; set; }
public string Foo9 { get; set; }
public string Foo10 { get; set; }
public string Foo11 { get; set; }
public string Foo12 { get; set; }
public string Foo13 { get; set; }
public string Foo14 { get; set; }
public string Foo15 { get; set; }
public string Foo16 { get; set; }
public string Foo17 { get; set; }
public string Foo18 { get; set; }
public string Foo19 { get; set; }

}

public class Test
{
static void Main()
{
List<PropertyInfo> properties = new List<PropertyInfo>();
for (int i=0; i < 20; i++)
{
properties.Add(typeof(LotsOfProperties).
GetProperty("Foo"+i));
}

Stopwatch sw = Stopwatch.StartNew();
for (int i=0; i < 66000; i++)
{
object o = Activator.CreateInstance
(typeof(LotsOfProperties));
foreach (PropertyInfo prop in properties)
{
prop.SetValue(o, "Value", null);
}
}
sw.Stop();
Console.WriteLine (sw.ElapsedMilliseconds);
}

}

Jon, I hadn't got around to running the stopwatch test yet and your
results make it look like I don't have to worry about the time to run
a PropertyInfo.SetValue() on a given object/value pair. So I'm
guessing that the code is taking too long probably because it is
looking up the property info each time and because the algorithms in
the set properties long.

This is great to know. I'll keep a tab on that link you provided too,
just in case I need it for something else.

Thanks a lot, Jon!
Nora
 
probably because it is looking up the property info each time

Absolutely; when I was looking into this area (for a flexibile data-
export process), I found that pre-obtaining the getter was a
significant saving by itself (regardless of whether that is a
PropertyInfo or a sneaky PropertyDescriptor) - so what I did was to
build a PropertyDescriptor-array and pre-fill it with the getters that
I needed - then my main output code was essentially:

foreach(row in data) {
startRow();
foreach(prop in propsWanted) {
writeValue(); // from prop and row
}
endRow();
}

Depending on your data, this might be enough... but then, since it
only takes one line of code to swap a reflection-based descriptor for
a dynamic IL-based descriptor, it is trivial to try it before and
after.

Marc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top