├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── appveyor.yml
├── assets
├── Hyper.ComponentModel.Source.nuspec
├── Hyper.ComponentModel.nuspec
├── icon.png
└── pack.ps1
└── src
├── .nuget
├── NuGet.Config
├── NuGet.exe
└── NuGet.targets
├── Hyper.ComponentModel.Example
├── Descriptors
│ └── MyEntityNamePropertyDescriptor.cs
├── Entites
│ ├── MyEntity.cs
│ └── MySuperEntity.cs
├── Hyper.ComponentModel.Example.csproj
├── Program.cs
└── Properties
│ └── AssemblyInfo.cs
├── Hyper.ComponentModel
├── ChainingPropertyDescriptor.cs
├── Hyper.ComponentModel.csproj
├── HyperTypeDescriptionProvider.cs
├── HyperTypeDescriptor.cs
└── Properties
│ └── AssemblyInfo.cs
└── HyperPropertyDescriptor.sln
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 |
11 | [Dd]ebug/
12 | [Rr]elease/
13 | x64/
14 | build/
15 | [Bb]in/
16 | [Oo]bj/
17 |
18 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
19 | !packages/*/build/
20 |
21 | # MSTest test Results
22 | [Tt]est[Rr]esult*/
23 | [Bb]uild[Ll]og.*
24 |
25 | *_i.c
26 | *_p.c
27 | *.ilk
28 | *.meta
29 | *.obj
30 | *.pch
31 | *.pdb
32 | *.pgc
33 | *.pgd
34 | *.rsp
35 | *.sbr
36 | *.tlb
37 | *.tli
38 | *.tlh
39 | *.tmp
40 | *.tmp_proj
41 | *.log
42 | *.vspscc
43 | *.vssscc
44 | .builds
45 | *.pidb
46 | *.log
47 | *.scc
48 |
49 | # Visual C++ cache files
50 | ipch/
51 | *.aps
52 | *.ncb
53 | *.opensdf
54 | *.sdf
55 | *.cachefile
56 |
57 | # Visual Studio profiler
58 | *.psess
59 | *.vsp
60 | *.vspx
61 |
62 | # Guidance Automation Toolkit
63 | *.gpState
64 |
65 | # ReSharper is a .NET coding add-in
66 | _ReSharper*/
67 | *.[Rr]e[Ss]harper
68 |
69 | # TeamCity is a build add-in
70 | _TeamCity*
71 |
72 | # DotCover is a Code Coverage Tool
73 | *.dotCover
74 |
75 | # NCrunch
76 | *.ncrunch*
77 | .*crunch*.local.xml
78 |
79 | # Installshield output folder
80 | [Ee]xpress/
81 |
82 | # DocProject is a documentation generator add-in
83 | DocProject/buildhelp/
84 | DocProject/Help/*.HxT
85 | DocProject/Help/*.HxC
86 | DocProject/Help/*.hhc
87 | DocProject/Help/*.hhk
88 | DocProject/Help/*.hhp
89 | DocProject/Help/Html2
90 | DocProject/Help/html
91 |
92 | # Click-Once directory
93 | publish/
94 |
95 | # Publish Web Output
96 | *.Publish.xml
97 |
98 | # NuGet Packages Directory
99 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
100 | packages/
101 |
102 | # Windows Azure Build Output
103 | csx
104 | *.build.csdef
105 |
106 | # Windows Store app package directory
107 | AppPackages/
108 |
109 | # Others
110 | sql/
111 | *.Cache
112 | ClientBin/
113 | [Ss]tyle[Cc]op.*
114 | ~$*
115 | *~
116 | *.dbmdl
117 | *.[Pp]ublish.xml
118 | *.pfx
119 | *.publishsettings
120 |
121 | # RIA/Silverlight projects
122 | Generated_Code/
123 |
124 | # Backup & report files from converting an old project file to a newer
125 | # Visual Studio version. Backup files are not needed, because we have git ;-)
126 | _UpgradeReport_Files/
127 | Backup*/
128 | UpgradeLog*.XML
129 | UpgradeLog*.htm
130 |
131 | # SQL Server files
132 | App_Data/*.mdf
133 | App_Data/*.ldf
134 |
135 |
136 | #LightSwitch generated files
137 | GeneratedArtifacts/
138 | _Pvt_Extensions/
139 | ModelManifest.xml
140 |
141 | # =========================
142 | # Windows detritus
143 | # =========================
144 |
145 | # Windows image file caches
146 | Thumbs.db
147 | ehthumbs.db
148 |
149 | # Folder config file
150 | Desktop.ini
151 |
152 | # Recycle Bin used on file shares
153 | $RECYCLE.BIN/
154 |
155 | # Mac desktop service store files
156 | .DS_Store
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Pavel Nosovich
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | HyperPropertyDescriptor [](https://ci.appveyor.com/project/forcewake/hyperpropertydescriptor)
2 | =======================
3 | 
4 |
5 | Provides a vastly accelerate runtime property implementation that can be applied even to closed-source classes
6 |
7 | ## Source
8 |
9 | Based on the code from the [Marc Gravell article][1]
10 |
11 | [1]: http://www.codeproject.com/Articles/18450/HyperDescriptor-Accelerated-dynamic-property-acces
12 |
13 | ## Results
14 |
15 | ### MyEntity.Name with 25000000 operations
16 |
17 | | Operation | Direct | Without Provider | With Provider |
18 | |---------------------- |------- |----------------- |-------------- |
19 | | GetProperties | | 647ms | 699ms |
20 | | IsReadOnly | | 2926ms | 43ms |
21 | | SupportsChangeEvents | | 245ms | 41ms |
22 | | GetValue | 8ms | 10360ms | 57ms |
23 | | SetValue | 97ms | 20288ms | 155ms |
24 | | ValueChanged | 1022ms | 29566ms | 954ms |
25 |
26 | ### MySuperEntity.Name with 25000000 operations
27 |
28 | | Operation | Without Provider | With Provider |
29 | |---------------------- |----------------- |-------------- |
30 | | GetProperties | 828ms | 914ms |
31 | | IsReadOnly | 2881ms | 41ms |
32 | | SupportsChangeEvents | 241ms | 44ms |
33 | | GetValue | 10682ms | 95ms |
34 | | SetValue | 20730ms | 173ms |
35 | | ValueChanged | 30979ms | 1059ms |
36 |
37 | ### MySuperEntity.When with 10000000 operations
38 |
39 | | Operation | Without Provider | With Provider |
40 | |---------------------- |------------------ |--------------- |
41 | | GetProperties | 825ms | 891ms |
42 | | IsReadOnly | 2888ms | 41ms |
43 | | SupportsChangeEvents | 251ms | 46ms |
44 | | GetValue | 11393ms | 295ms |
45 | | SetValue | 22416ms | 110ms |
46 |
47 | ## Example
48 |
49 | Just write this piece of code:
50 |
51 | ```csharp
52 | HyperTypeDescriptionProvider.Add(typeof (MyEntity));
53 | ```
54 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | version: 1.0.{build}
2 |
3 | branches:
4 | only:
5 | - master
6 | except:
7 | - gh-pages
8 |
9 | assembly_info:
10 | patch: true
11 | file: AssemblyInfo.*
12 | assembly_version: "{version}"
13 | assembly_file_version: "{version}"
14 | assembly_informational_version: "{version}"
15 |
16 | configuration: Release
17 |
18 | build:
19 | project: src/HyperPropertyDescriptor.sln
20 |
21 | after_test:
22 | - ps: .\assets\pack.ps1
23 |
24 | artifacts:
25 | # pushing all *.nupkg files in directory
26 | - path: '**\*.nupkg' # find all NuGet packages recursively
27 |
28 | deploy:
29 | provider: NuGet
30 | api_key:
31 | secure: yNaPU9GGsdDdMjOB5tbQTuIIq4DFHNGUkZP1ZTDDCKQG3g7pZjxcBFZblTMeIawA
32 |
--------------------------------------------------------------------------------
/assets/Hyper.ComponentModel.Source.nuspec:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/forcewake/HyperPropertyDescriptor/8f740a9a41e1f0ca7dd9a20f156a066fd8738245/assets/Hyper.ComponentModel.Source.nuspec
--------------------------------------------------------------------------------
/assets/Hyper.ComponentModel.nuspec:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/forcewake/HyperPropertyDescriptor/8f740a9a41e1f0ca7dd9a20f156a066fd8738245/assets/Hyper.ComponentModel.nuspec
--------------------------------------------------------------------------------
/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/forcewake/HyperPropertyDescriptor/8f740a9a41e1f0ca7dd9a20f156a066fd8738245/assets/icon.png
--------------------------------------------------------------------------------
/assets/pack.ps1:
--------------------------------------------------------------------------------
1 | function Update-Version($path, $version) {
2 | $content = (Get-Content $path)
3 | $content = $content -replace '\$version\$', $version
4 | $content | Out-File $path
5 | }
6 |
7 | function Get-Version() {
8 | $version = [System.Reflection.Assembly]::LoadFile("$root\src\Hyper.ComponentModel\bin\Release\Hyper.ComponentModel.dll").GetName().Version
9 | $currentVersion = "{0}.{1}.{2}" -f ($version.Major, $version.Minor, $version.Build)
10 | return $currentVersion;
11 | }
12 |
13 | function Create-Package($path) {
14 | & $root\src\.nuget\NuGet.exe pack $path
15 | }
16 |
17 | $root = (split-path -parent $MyInvocation.MyCommand.Definition) + '\..'
18 | $hyperDescriptorNuspecPath = "$root\assets\Hyper.ComponentModel.nuspec"
19 | $hyperDescriptorSourceNuspecPath = "$root\assets\Hyper.ComponentModel.Source.nuspec"
20 |
21 | $version = Get-Version
22 |
23 | Write-Host "Setting .nuspec version tag to $version"
24 |
25 | Update-Version $hyperDescriptorSourceNuspecPath $version
26 | Update-Version $hyperDescriptorNuspecPath $version
27 |
28 | Create-Package $hyperDescriptorNuspecPath
29 | Create-Package $hyperDescriptorSourceNuspecPath
--------------------------------------------------------------------------------
/src/.nuget/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/.nuget/NuGet.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/forcewake/HyperPropertyDescriptor/8f740a9a41e1f0ca7dd9a20f156a066fd8738245/src/.nuget/NuGet.exe
--------------------------------------------------------------------------------
/src/.nuget/NuGet.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildProjectDirectory)\..\
5 |
6 |
7 | false
8 |
9 |
10 | false
11 |
12 |
13 | true
14 |
15 |
16 | false
17 |
18 |
19 |
20 |
21 |
22 |
26 |
27 |
28 |
29 |
30 | $([System.IO.Path]::Combine($(SolutionDir), ".nuget"))
31 |
32 |
33 |
34 |
35 | $(SolutionDir).nuget
36 |
37 |
38 |
39 | $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config
40 | $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config
41 |
42 |
43 |
44 | $(MSBuildProjectDirectory)\packages.config
45 | $(PackagesProjectConfig)
46 |
47 |
48 |
49 |
50 | $(NuGetToolsPath)\NuGet.exe
51 | @(PackageSource)
52 |
53 | "$(NuGetExePath)"
54 | mono --runtime=v4.0.30319 "$(NuGetExePath)"
55 |
56 | $(TargetDir.Trim('\\'))
57 |
58 | -RequireConsent
59 | -NonInteractive
60 |
61 | "$(SolutionDir) "
62 | "$(SolutionDir)"
63 |
64 |
65 | $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)
66 | $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols
67 |
68 |
69 |
70 | RestorePackages;
71 | $(BuildDependsOn);
72 |
73 |
74 |
75 |
76 | $(BuildDependsOn);
77 | BuildPackage;
78 |
79 |
80 |
81 |
82 |
83 |
84 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
99 |
100 |
103 |
104 |
105 |
106 |
108 |
109 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
141 |
142 |
143 |
144 |
145 |
--------------------------------------------------------------------------------
/src/Hyper.ComponentModel.Example/Descriptors/MyEntityNamePropertyDescriptor.cs:
--------------------------------------------------------------------------------
1 | namespace Hyper.ComponentModel.Example.Descriptors
2 | {
3 | using System;
4 | using System.ComponentModel;
5 | using Hyper.ComponentModel.Example.Entites;
6 |
7 | public sealed class MyEntityNamePropertyDescriptor : ChainingPropertyDescriptor
8 | {
9 | public MyEntityNamePropertyDescriptor(PropertyDescriptor parent) : base(parent)
10 | {
11 | }
12 |
13 | public override object GetValue(object component)
14 | {
15 | return ((MyEntity) component).Name;
16 | }
17 |
18 | public override void SetValue(object component, object value)
19 | {
20 | ((MyEntity) component).Name = (string) value;
21 | }
22 |
23 | public override bool IsReadOnly
24 | {
25 | get { return false; }
26 | }
27 |
28 | public override bool SupportsChangeEvents
29 | {
30 | get { return true; }
31 | }
32 |
33 | public override void AddValueChanged(object component, EventHandler handler)
34 | {
35 | ((MyEntity) component).NameChanged += handler;
36 | }
37 |
38 | public override void RemoveValueChanged(object component, EventHandler handler)
39 | {
40 | ((MyEntity) component).NameChanged -= handler;
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/src/Hyper.ComponentModel.Example/Entites/MyEntity.cs:
--------------------------------------------------------------------------------
1 | namespace Hyper.ComponentModel.Example.Entites
2 | {
3 | using System;
4 |
5 | public class MyEntity
6 | {
7 | // opCount is a marker of work done; make protected (as an exception)
8 | // to minimise impact
9 | protected int opCount;
10 | private string name;
11 | private EventHandler _nameChanged;
12 |
13 | public event EventHandler NameChanged
14 | {
15 | add
16 | {
17 | opCount++;
18 | _nameChanged += value;
19 | }
20 | remove
21 | {
22 | opCount++;
23 | _nameChanged -= value;
24 | }
25 | }
26 |
27 | public string Name
28 | {
29 | get
30 | {
31 | opCount++;
32 | return name;
33 | }
34 | set
35 | {
36 | opCount++;
37 | if (value != Name)
38 | {
39 | name = value;
40 | EventHandler handler = _nameChanged;
41 | if (handler != null)
42 | {
43 | handler(this, EventArgs.Empty);
44 | }
45 | }
46 | }
47 | }
48 |
49 | public int OpCount
50 | {
51 | get { return opCount; }
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/src/Hyper.ComponentModel.Example/Entites/MySuperEntity.cs:
--------------------------------------------------------------------------------
1 | namespace Hyper.ComponentModel.Example.Entites
2 | {
3 | using System;
4 |
5 | public class MySuperEntity : MyEntity
6 | {
7 | private DateTime when;
8 |
9 | public DateTime When
10 | {
11 | get
12 | {
13 | opCount++;
14 | return when;
15 | }
16 | set
17 | {
18 | opCount++;
19 | when = value;
20 | }
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/src/Hyper.ComponentModel.Example/Hyper.ComponentModel.Example.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {77094346-EBD5-4D78-B036-C90C6B5B98D8}
8 | Exe
9 | Properties
10 | Hyper.ComponentModel.Example
11 | Hyper.ComponentModel.Example
12 | v3.5
13 | 512
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}
52 | Hyper.ComponentModel
53 |
54 |
55 |
56 |
63 |
--------------------------------------------------------------------------------
/src/Hyper.ComponentModel.Example/Program.cs:
--------------------------------------------------------------------------------
1 | namespace Hyper.ComponentModel.Example
2 | {
3 | using System;
4 | using System.ComponentModel;
5 | using System.Diagnostics;
6 | using System.Security.Permissions;
7 | using Hyper.ComponentModel.Example.Entites;
8 |
9 | internal class Program
10 | {
11 | ///
12 | /// The number of standard operations (GetValue(), etc) to perform
13 | ///
14 | private const int Cycles = 5000000;
15 |
16 | ///
17 | /// The number of times to invoke GetProperties (slower)
18 | ///
19 | private const int MetaCycles = 100000;
20 |
21 | private static void Main(string[] args)
22 | {
23 | // verify that things work OK without reflection access
24 | var permission = new ReflectionPermission(ReflectionPermissionFlag.AllFlags);
25 | permission.Deny();
26 |
27 | Console.WriteLine("Direct access");
28 | TestDirect(1, false); // for JIT etc
29 | TestDirect(Cycles, true);
30 |
31 | Console.WriteLine();
32 | string typeName = typeof (HyperTypeDescriptionProvider).Name;
33 | Console.WriteLine("Without " + typeName);
34 |
35 | RunTests(1, 1, false); // for JIT etc
36 | RunTests(MetaCycles, Cycles, true);
37 |
38 | HyperTypeDescriptionProvider.Add(typeof (MyEntity));
39 | Console.WriteLine();
40 | Console.WriteLine("With " + typeName);
41 |
42 | RunTests(1, 1, false); // for Emit, JIT etc
43 | RunTests(MetaCycles, Cycles, true);
44 |
45 | Console.ReadLine();
46 | }
47 |
48 | private static void RunTests(int metaCount, int count, bool report)
49 | {
50 | // note: GC.Collect here in timing mode (report==true) to
51 | // minimise chance of increasing object count triggering GC
52 | // for later tests. Not recommended for production code, but
53 | // acceptable for levelling the field in performance tests.
54 | if (report)
55 | {
56 | GC.Collect();
57 | }
58 | Test(metaCount, count, "Name", report);
59 | if (report)
60 | {
61 | GC.Collect();
62 | }
63 | Test(metaCount, count, "Name", report);
64 | if (report)
65 | {
66 | GC.Collect();
67 | }
68 | Test(metaCount, count, "When", report);
69 | if (report)
70 | {
71 | GC.Collect();
72 | }
73 | }
74 |
75 | private static void TestDirect(int count, bool output)
76 | {
77 | // initialise
78 | MyEntity t = new MyEntity();
79 | string value = "";
80 |
81 | // GetValue
82 | Stopwatch getValue = new Stopwatch();
83 | getValue.Start();
84 | for (int i = 0; i < count; i++)
85 | {
86 | value = t.Name;
87 | }
88 | getValue.Stop();
89 |
90 | // SetValue
91 | Stopwatch setValue = new Stopwatch();
92 | setValue.Start();
93 | for (int i = 0; i < count; i++)
94 | {
95 | t.Name = value;
96 | }
97 | setValue.Stop();
98 |
99 | // ValueChanged
100 | Stopwatch valueChanged = new Stopwatch();
101 | valueChanged.Start();
102 | EventHandler handler = ValueChanged;
103 | for (int i = 0; i < count; i++)
104 | {
105 | t.NameChanged += handler;
106 | t.NameChanged -= handler;
107 | }
108 | valueChanged.Stop();
109 |
110 | if (output)
111 | {
112 | Report("Name", "GetValue", getValue);
113 | Report("Name", "SetValue", setValue);
114 | Report("Name", "ValueChanged", valueChanged);
115 | Console.WriteLine("OpCount: " + t.OpCount);
116 | }
117 | }
118 |
119 | private static void Test(int metaCount, int count, string name, bool output) where T : MyEntity, new()
120 | {
121 | // initialise
122 | T t = new T();
123 | PropertyDescriptorCollection props = null;
124 | PropertyDescriptor property = null;
125 | object value = null;
126 | bool isReadOnly = true, supportsChangeEvents = false;
127 |
128 | // GetProperties
129 | Stopwatch getProperties = new Stopwatch();
130 | getProperties.Start();
131 | for (int i = 0; i < metaCount; i++)
132 | {
133 | props = TypeDescriptor.GetProperties(t);
134 | }
135 | getProperties.Stop();
136 | if (props != null) property = props[name];
137 |
138 | // IsReadOnly
139 | Stopwatch isReadOnlyWatch = new Stopwatch();
140 | isReadOnlyWatch.Start();
141 | for (int i = 0; i < count; i++)
142 | {
143 | isReadOnly = property.IsReadOnly;
144 | }
145 | isReadOnlyWatch.Stop();
146 |
147 | // SupportsNotification
148 | Stopwatch supportsChangeEventsWatch = new Stopwatch();
149 | supportsChangeEventsWatch.Start();
150 | for (int i = 0; i < count; i++)
151 | {
152 | supportsChangeEvents = property.SupportsChangeEvents;
153 | }
154 | supportsChangeEventsWatch.Stop();
155 |
156 | // GetValue
157 | Stopwatch getValue = new Stopwatch();
158 | getValue.Start();
159 | for (int i = 0; i < count; i++)
160 | {
161 | value = property.GetValue(t);
162 | }
163 | getValue.Stop();
164 |
165 | // SetValue
166 | Stopwatch setValue = new Stopwatch();
167 | if (!isReadOnly)
168 | {
169 | setValue.Start();
170 | for (int i = 0; i < count; i++)
171 | {
172 | property.SetValue(t, value);
173 | }
174 | setValue.Stop();
175 | }
176 |
177 | // ValueChanged
178 | Stopwatch valueChanged = new Stopwatch();
179 | if (supportsChangeEvents)
180 | {
181 | EventHandler handler = ValueChanged;
182 | valueChanged.Start();
183 | for (int i = 0; i < count; i++)
184 | {
185 | property.AddValueChanged(t, handler);
186 | property.RemoveValueChanged(t, handler);
187 | }
188 | valueChanged.Stop();
189 | }
190 |
191 | if (output)
192 | {
193 | Report(name, "GetProperties", getProperties);
194 | Report(name, "IsReadOnly", isReadOnlyWatch);
195 | Report(name, "SupportsChangeEvents", supportsChangeEventsWatch);
196 | Report(name, "GetValue", getValue);
197 | if (!isReadOnly)
198 | {
199 | Report(name, "SetValue", setValue);
200 | }
201 | if (supportsChangeEvents)
202 | {
203 | Report(name, "ValueChanged", valueChanged);
204 | }
205 | Console.WriteLine("OpCount: " + t.OpCount);
206 | }
207 | }
208 |
209 | private static void Report(string propertyname, string test, Stopwatch watch)
210 | {
211 | int ms = (int) Math.Round(watch.Elapsed.TotalMilliseconds);
212 | Console.WriteLine("{0}.{1}\t{2}\t{3}ms", typeof (T).Name, propertyname, test, ms);
213 | }
214 |
215 | private static void ValueChanged(object sender, EventArgs args)
216 | {
217 | }
218 | }
219 | }
--------------------------------------------------------------------------------
/src/Hyper.ComponentModel.Example/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Hyper.ComponentModel.Example")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Hyper.ComponentModel.Example")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("a8121f86-2c20-4734-b19a-ddec48d99df0")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/src/Hyper.ComponentModel/ChainingPropertyDescriptor.cs:
--------------------------------------------------------------------------------
1 | namespace Hyper.ComponentModel
2 | {
3 | using System;
4 | using System.ComponentModel;
5 |
6 | public abstract class ChainingPropertyDescriptor : PropertyDescriptor
7 | {
8 | private readonly PropertyDescriptor _root;
9 |
10 | protected PropertyDescriptor Root
11 | {
12 | get { return _root; }
13 | }
14 |
15 | protected ChainingPropertyDescriptor(PropertyDescriptor root)
16 | : base(root)
17 | {
18 | _root = root;
19 | }
20 |
21 | public override void AddValueChanged(object component, EventHandler handler)
22 | {
23 | Root.AddValueChanged(component, handler);
24 | }
25 |
26 | public override AttributeCollection Attributes
27 | {
28 | get { return Root.Attributes; }
29 | }
30 |
31 | public override bool CanResetValue(object component)
32 | {
33 | return Root.CanResetValue(component);
34 | }
35 |
36 | public override string Category
37 | {
38 | get { return Root.Category; }
39 | }
40 |
41 | public override Type ComponentType
42 | {
43 | get { return Root.ComponentType; }
44 | }
45 |
46 | public override TypeConverter Converter
47 | {
48 | get { return Root.Converter; }
49 | }
50 |
51 | public override string Description
52 | {
53 | get { return Root.Description; }
54 | }
55 |
56 | public override bool DesignTimeOnly
57 | {
58 | get { return Root.DesignTimeOnly; }
59 | }
60 |
61 | public override string DisplayName
62 | {
63 | get { return Root.DisplayName; }
64 | }
65 |
66 | public override bool Equals(object obj)
67 | {
68 | return Root.Equals(obj);
69 | }
70 |
71 | public override PropertyDescriptorCollection GetChildProperties(object instance, Attribute[] filter)
72 | {
73 | return Root.GetChildProperties(instance, filter);
74 | }
75 |
76 | public override object GetEditor(Type editorBaseType)
77 | {
78 | return Root.GetEditor(editorBaseType);
79 | }
80 |
81 | public override int GetHashCode()
82 | {
83 | return Root.GetHashCode();
84 | }
85 |
86 | public override object GetValue(object component)
87 | {
88 | return Root.GetValue(component);
89 | }
90 |
91 | public override bool IsBrowsable
92 | {
93 | get { return Root.IsBrowsable; }
94 | }
95 |
96 | public override bool IsLocalizable
97 | {
98 | get { return Root.IsLocalizable; }
99 | }
100 |
101 | public override bool IsReadOnly
102 | {
103 | get { return Root.IsReadOnly; }
104 | }
105 |
106 | public override string Name
107 | {
108 | get { return Root.Name; }
109 | }
110 |
111 | public override Type PropertyType
112 | {
113 | get { return Root.PropertyType; }
114 | }
115 |
116 | public override void RemoveValueChanged(object component, EventHandler handler)
117 | {
118 | Root.RemoveValueChanged(component, handler);
119 | }
120 |
121 | public override void ResetValue(object component)
122 | {
123 | Root.ResetValue(component);
124 | }
125 |
126 | public override void SetValue(object component, object value)
127 | {
128 | Root.SetValue(component, value);
129 | }
130 |
131 | public override bool ShouldSerializeValue(object component)
132 | {
133 | return Root.ShouldSerializeValue(component);
134 | }
135 |
136 | public override bool SupportsChangeEvents
137 | {
138 | get { return Root.SupportsChangeEvents; }
139 | }
140 |
141 | public override string ToString()
142 | {
143 | return Root.ToString();
144 | }
145 | }
146 | }
--------------------------------------------------------------------------------
/src/Hyper.ComponentModel/Hyper.ComponentModel.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}
8 | Library
9 | Properties
10 | Hyper.ComponentModel
11 | Hyper.ComponentModel
12 | v3.5
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 | bin\Release\Hyper.ComponentModel.XML
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
55 |
--------------------------------------------------------------------------------
/src/Hyper.ComponentModel/HyperTypeDescriptionProvider.cs:
--------------------------------------------------------------------------------
1 | namespace Hyper.ComponentModel
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 | using System.ComponentModel;
6 | using System.Security;
7 | using System.Security.Permissions;
8 |
9 | public sealed class HyperTypeDescriptionProvider : TypeDescriptionProvider
10 | {
11 | public static void Add(Type type)
12 | {
13 | TypeDescriptionProvider parent = TypeDescriptor.GetProvider(type);
14 | TypeDescriptor.AddProvider(new HyperTypeDescriptionProvider(parent), type);
15 | }
16 |
17 | public HyperTypeDescriptionProvider() : this(typeof (object))
18 | {
19 | }
20 |
21 | public HyperTypeDescriptionProvider(Type type) : this(TypeDescriptor.GetProvider(type))
22 | {
23 | }
24 |
25 | public HyperTypeDescriptionProvider(TypeDescriptionProvider parent) : base(parent)
26 | {
27 | }
28 |
29 | public static void Clear(Type type)
30 | {
31 | lock (descriptors)
32 | {
33 | descriptors.Remove(type);
34 | }
35 | }
36 |
37 | public static void Clear()
38 | {
39 | lock (descriptors)
40 | {
41 | descriptors.Clear();
42 | }
43 | }
44 |
45 | private static readonly Dictionary descriptors =
46 | new Dictionary();
47 |
48 | public override sealed ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
49 | {
50 | lock (descriptors)
51 | {
52 | ICustomTypeDescriptor descriptor;
53 | if (!descriptors.TryGetValue(objectType, out descriptor))
54 | {
55 | try
56 | {
57 | descriptor = BuildDescriptor(objectType);
58 | }
59 | catch
60 | {
61 | return base.GetTypeDescriptor(objectType, instance);
62 | }
63 | }
64 | return descriptor;
65 | }
66 | }
67 |
68 | [SecuritySafeCritical]
69 | [ReflectionPermission(SecurityAction.Assert, Unrestricted = true)]
70 | private ICustomTypeDescriptor BuildDescriptor(Type objectType)
71 | {
72 | // NOTE: "descriptors" already locked here
73 |
74 | // get the parent descriptor and add to the dictionary so that
75 | // building the new descriptor will use the base rather than recursing
76 | ICustomTypeDescriptor descriptor = base.GetTypeDescriptor(objectType, null);
77 | descriptors.Add(objectType, descriptor);
78 | try
79 | {
80 | // build a new descriptor from this, and replace the lookup
81 | descriptor = new HyperTypeDescriptor(descriptor);
82 | descriptors[objectType] = descriptor;
83 | return descriptor;
84 | }
85 | catch
86 | {
87 | // rollback and throw
88 | // (perhaps because the specific caller lacked permissions;
89 | // another caller may be successful)
90 | descriptors.Remove(objectType);
91 | throw;
92 | }
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/Hyper.ComponentModel/HyperTypeDescriptor.cs:
--------------------------------------------------------------------------------
1 | namespace Hyper.ComponentModel
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 | using System.ComponentModel;
6 | using System.Reflection;
7 | using System.Reflection.Emit;
8 | using System.Threading;
9 |
10 | public sealed class HyperTypeDescriptor : CustomTypeDescriptor
11 | {
12 | private readonly PropertyDescriptorCollection propertyCollections;
13 |
14 | private static readonly Dictionary properties =
15 | new Dictionary();
16 |
17 | internal HyperTypeDescriptor(ICustomTypeDescriptor parent)
18 | : base(parent)
19 | {
20 | propertyCollections = WrapProperties(parent.GetProperties());
21 | }
22 |
23 | public override sealed PropertyDescriptorCollection GetProperties(Attribute[] attributes)
24 | {
25 | return propertyCollections;
26 | }
27 |
28 | public override sealed PropertyDescriptorCollection GetProperties()
29 | {
30 | return propertyCollections;
31 | }
32 |
33 | private static PropertyDescriptorCollection WrapProperties(PropertyDescriptorCollection oldProps)
34 | {
35 | PropertyDescriptor[] newProps = new PropertyDescriptor[oldProps.Count];
36 | int index = 0;
37 | bool changed = false;
38 | // HACK: how to identify reflection, given that the class is internal...
39 | Type wrapMe =
40 | Assembly.GetAssembly(typeof (PropertyDescriptor))
41 | .GetType("System.ComponentModel.ReflectPropertyDescriptor");
42 | foreach (PropertyDescriptor oldProp in oldProps)
43 | {
44 | PropertyDescriptor pd = oldProp;
45 | // if it looks like reflection, try to create a bespoke descriptor
46 | if (ReferenceEquals(wrapMe, pd.GetType()) && TryCreatePropertyDescriptor(ref pd))
47 | {
48 | changed = true;
49 | }
50 | newProps[index++] = pd;
51 | }
52 |
53 | return changed ? new PropertyDescriptorCollection(newProps, true) : oldProps;
54 | }
55 |
56 | private static readonly ModuleBuilder moduleBuilder;
57 | private static int counter;
58 |
59 | static HyperTypeDescriptor()
60 | {
61 | AssemblyName an = new AssemblyName("Hyper.ComponentModel.dynamic");
62 | AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
63 | moduleBuilder = ab.DefineDynamicModule("Hyper.ComponentModel.dynamic.dll");
64 |
65 | }
66 |
67 | private static bool TryCreatePropertyDescriptor(ref PropertyDescriptor descriptor)
68 | {
69 | try
70 | {
71 | PropertyInfo property = descriptor.ComponentType.GetProperty(descriptor.Name);
72 | if (property == null) return false;
73 |
74 | lock (properties)
75 | {
76 | PropertyDescriptor foundBuiltAlready;
77 | if (properties.TryGetValue(property, out foundBuiltAlready))
78 | {
79 | descriptor = foundBuiltAlready;
80 | return true;
81 | }
82 |
83 | string name = "_c" + Interlocked.Increment(ref counter).ToString();
84 | TypeBuilder tb = moduleBuilder.DefineType(name,
85 | TypeAttributes.Sealed | TypeAttributes.NotPublic | TypeAttributes.Class |
86 | TypeAttributes.BeforeFieldInit | TypeAttributes.AutoClass | TypeAttributes.Public,
87 | typeof (ChainingPropertyDescriptor));
88 |
89 | // ctor calls base
90 | ConstructorBuilder cb =
91 | tb.DefineConstructor(
92 | MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.SpecialName |
93 | MethodAttributes.RTSpecialName, CallingConventions.Standard,
94 | new Type[] {typeof (PropertyDescriptor)});
95 | ILGenerator il = cb.GetILGenerator();
96 | il.Emit(OpCodes.Ldarg_0);
97 | il.Emit(OpCodes.Ldarg_1);
98 | il.Emit(OpCodes.Call,
99 | typeof (ChainingPropertyDescriptor).GetConstructor(
100 | BindingFlags.NonPublic | BindingFlags.Instance, null,
101 | new Type[] {typeof (PropertyDescriptor)}, null));
102 | il.Emit(OpCodes.Ret);
103 |
104 | MethodBuilder mb;
105 | MethodInfo baseMethod;
106 | if (property.CanRead)
107 | {
108 | // obtain the implementation that we want to override
109 | baseMethod = typeof (ChainingPropertyDescriptor).GetMethod("GetValue");
110 | // create a new method that accepts an object and returns an object (as per the base)
111 | mb = tb.DefineMethod(baseMethod.Name,
112 | MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual |
113 | MethodAttributes.Final,
114 | baseMethod.CallingConvention, baseMethod.ReturnType, new Type[] {typeof (object)});
115 | // start writing IL into the method
116 | il = mb.GetILGenerator();
117 | if (property.DeclaringType.IsValueType)
118 | {
119 | // upbox the object argument into our known (instance) struct type
120 | LocalBuilder lb = il.DeclareLocal(property.DeclaringType);
121 | il.Emit(OpCodes.Ldarg_1);
122 | il.Emit(OpCodes.Unbox_Any, property.DeclaringType);
123 | il.Emit(OpCodes.Stloc_0);
124 | il.Emit(OpCodes.Ldloca_S, lb);
125 | }
126 | else
127 | {
128 | // cast the object argument into our known class type
129 | il.Emit(OpCodes.Ldarg_1);
130 | il.Emit(OpCodes.Castclass, property.DeclaringType);
131 | }
132 | // call the "get" method
133 | il.Emit(OpCodes.Callvirt, property.GetGetMethod());
134 |
135 | if (property.PropertyType.IsValueType)
136 | {
137 | // box it from the known (value) struct type
138 | il.Emit(OpCodes.Box, property.PropertyType);
139 | }
140 | // return the value
141 | il.Emit(OpCodes.Ret);
142 | // signal that this method should override the base
143 | tb.DefineMethodOverride(mb, baseMethod);
144 | }
145 |
146 | bool supportsChangeEvents = descriptor.SupportsChangeEvents, isReadOnly = descriptor.IsReadOnly;
147 |
148 | // override SupportsChangeEvents
149 | baseMethod = typeof (ChainingPropertyDescriptor).GetProperty("SupportsChangeEvents").GetGetMethod();
150 | mb = tb.DefineMethod(baseMethod.Name,
151 | MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual |
152 | MethodAttributes.Final | MethodAttributes.SpecialName, baseMethod.CallingConvention,
153 | baseMethod.ReturnType, Type.EmptyTypes);
154 | il = mb.GetILGenerator();
155 | if (supportsChangeEvents)
156 | {
157 | il.Emit(OpCodes.Ldc_I4_1);
158 | }
159 | else
160 | {
161 | il.Emit(OpCodes.Ldc_I4_0);
162 | }
163 | il.Emit(OpCodes.Ret);
164 | tb.DefineMethodOverride(mb, baseMethod);
165 |
166 | // override IsReadOnly
167 | baseMethod = typeof (ChainingPropertyDescriptor).GetProperty("IsReadOnly").GetGetMethod();
168 | mb = tb.DefineMethod(baseMethod.Name,
169 | MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual |
170 | MethodAttributes.Final | MethodAttributes.SpecialName, baseMethod.CallingConvention,
171 | baseMethod.ReturnType, Type.EmptyTypes);
172 | il = mb.GetILGenerator();
173 | if (isReadOnly)
174 | {
175 | il.Emit(OpCodes.Ldc_I4_1);
176 | }
177 | else
178 | {
179 | il.Emit(OpCodes.Ldc_I4_0);
180 | }
181 | il.Emit(OpCodes.Ret);
182 | tb.DefineMethodOverride(mb, baseMethod);
183 |
184 | // for classes, implement write (would be lost in unbox for structs)
185 | if (!property.DeclaringType.IsValueType)
186 | {
187 | if (!isReadOnly && property.CanWrite)
188 | {
189 | // override set method
190 | baseMethod = typeof (ChainingPropertyDescriptor).GetMethod("SetValue");
191 | mb = tb.DefineMethod(baseMethod.Name,
192 | MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual |
193 | MethodAttributes.Final, baseMethod.CallingConvention, baseMethod.ReturnType,
194 | new Type[] {typeof (object), typeof (object)});
195 | il = mb.GetILGenerator();
196 | il.Emit(OpCodes.Ldarg_1);
197 | il.Emit(OpCodes.Castclass, property.DeclaringType);
198 | il.Emit(OpCodes.Ldarg_2);
199 | if (property.PropertyType.IsValueType)
200 | {
201 | il.Emit(OpCodes.Unbox_Any, property.PropertyType);
202 | }
203 | else
204 | {
205 | il.Emit(OpCodes.Castclass, property.PropertyType);
206 | }
207 | il.Emit(OpCodes.Callvirt, property.GetSetMethod());
208 | il.Emit(OpCodes.Ret);
209 | tb.DefineMethodOverride(mb, baseMethod);
210 | }
211 |
212 | if (supportsChangeEvents)
213 | {
214 | EventInfo ei = property.DeclaringType.GetEvent(property.Name + "Changed");
215 | if (ei != null)
216 | {
217 | baseMethod = typeof (ChainingPropertyDescriptor).GetMethod("AddValueChanged");
218 | mb = tb.DefineMethod(baseMethod.Name,
219 | MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual |
220 | MethodAttributes.Final | MethodAttributes.SpecialName, baseMethod.CallingConvention,
221 | baseMethod.ReturnType, new Type[] {typeof (object), typeof (EventHandler)});
222 | il = mb.GetILGenerator();
223 | il.Emit(OpCodes.Ldarg_1);
224 | il.Emit(OpCodes.Castclass, property.DeclaringType);
225 | il.Emit(OpCodes.Ldarg_2);
226 | il.Emit(OpCodes.Callvirt, ei.GetAddMethod());
227 | il.Emit(OpCodes.Ret);
228 | tb.DefineMethodOverride(mb, baseMethod);
229 |
230 | baseMethod = typeof (ChainingPropertyDescriptor).GetMethod("RemoveValueChanged");
231 | mb = tb.DefineMethod(baseMethod.Name,
232 | MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual |
233 | MethodAttributes.Final | MethodAttributes.SpecialName, baseMethod.CallingConvention,
234 | baseMethod.ReturnType, new Type[] {typeof (object), typeof (EventHandler)});
235 | il = mb.GetILGenerator();
236 | il.Emit(OpCodes.Ldarg_1);
237 | il.Emit(OpCodes.Castclass, property.DeclaringType);
238 | il.Emit(OpCodes.Ldarg_2);
239 | il.Emit(OpCodes.Callvirt, ei.GetRemoveMethod());
240 | il.Emit(OpCodes.Ret);
241 | tb.DefineMethodOverride(mb, baseMethod);
242 | }
243 | }
244 |
245 | }
246 | PropertyDescriptor newDesc =
247 | tb.CreateType()
248 | .GetConstructor(new Type[] {typeof (PropertyDescriptor)})
249 | .Invoke(new object[] {descriptor}) as PropertyDescriptor;
250 | if (newDesc == null)
251 | {
252 | return false;
253 | }
254 | descriptor = newDesc;
255 | properties.Add(property, descriptor);
256 | return true;
257 | }
258 | }
259 | catch
260 | {
261 | return false;
262 | }
263 | }
264 | }
265 | }
--------------------------------------------------------------------------------
/src/Hyper.ComponentModel/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Hyper.ComponentModel")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Hyper.ComponentModel")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("aa867666-4c7a-489b-98ac-ce79048bddfa")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/src/HyperPropertyDescriptor.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.30501.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hyper.ComponentModel", "Hyper.ComponentModel\Hyper.ComponentModel.csproj", "{3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{82742E28-6981-4EB9-97E1-7AA0EE36D5F2}"
9 | ProjectSection(SolutionItems) = preProject
10 | .nuget\NuGet.Config = .nuget\NuGet.Config
11 | .nuget\NuGet.exe = .nuget\NuGet.exe
12 | .nuget\NuGet.targets = .nuget\NuGet.targets
13 | EndProjectSection
14 | EndProject
15 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{42DA7FD8-C73C-486C-A753-D2F40A412DB2}"
16 | EndProject
17 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{039ED9B5-88BF-47ED-BFDB-522C3B24B7C5}"
18 | EndProject
19 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hyper.ComponentModel.Example", "Hyper.ComponentModel.Example\Hyper.ComponentModel.Example.csproj", "{77094346-EBD5-4D78-B036-C90C6B5B98D8}"
20 | EndProject
21 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{05676A7C-2D4F-4BF3-8A31-C67648E21E02}"
22 | EndProject
23 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "assets", "assets", "{F115C7FA-0E18-4C6D-A270-1EF743687EDE}"
24 | ProjectSection(SolutionItems) = preProject
25 | ..\appveyor.yml = ..\appveyor.yml
26 | ..\assets\Hyper.ComponentModel.nuspec = ..\assets\Hyper.ComponentModel.nuspec
27 | ..\assets\Hyper.ComponentModel.Source.nuspec = ..\assets\Hyper.ComponentModel.Source.nuspec
28 | ..\LICENSE = ..\LICENSE
29 | ..\assets\pack.ps1 = ..\assets\pack.ps1
30 | ..\README.md = ..\README.md
31 | EndProjectSection
32 | EndProject
33 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{3128F9F7-383F-4829-8C59-B7CD48365968}"
34 | EndProject
35 | Global
36 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
37 | Debug|Any CPU = Debug|Any CPU
38 | Release|Any CPU = Release|Any CPU
39 | EndGlobalSection
40 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
41 | {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
42 | {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.Debug|Any CPU.Build.0 = Debug|Any CPU
43 | {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.Release|Any CPU.ActiveCfg = Release|Any CPU
44 | {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.Release|Any CPU.Build.0 = Release|Any CPU
45 | {77094346-EBD5-4D78-B036-C90C6B5B98D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
46 | {77094346-EBD5-4D78-B036-C90C6B5B98D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
47 | {77094346-EBD5-4D78-B036-C90C6B5B98D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
48 | {77094346-EBD5-4D78-B036-C90C6B5B98D8}.Release|Any CPU.Build.0 = Release|Any CPU
49 | EndGlobalSection
50 | GlobalSection(SolutionProperties) = preSolution
51 | HideSolutionNode = FALSE
52 | EndGlobalSection
53 | GlobalSection(NestedProjects) = preSolution
54 | {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50} = {05676A7C-2D4F-4BF3-8A31-C67648E21E02}
55 | {77094346-EBD5-4D78-B036-C90C6B5B98D8} = {42DA7FD8-C73C-486C-A753-D2F40A412DB2}
56 | EndGlobalSection
57 | EndGlobal
58 |
--------------------------------------------------------------------------------