Coder Social home page Coder Social logo

whathecode / framework-class-library-extension Goto Github PK

View Code? Open in Web Editor NEW
21.0 6.0 12.0 1.92 MB

Highly reuseable classes I find to be missing in .NET's FCL.

Home Page: http://whathecode.wordpress.com/fcl-extension/

License: Other

C# 99.97% Shell 0.01% Batchfile 0.02%

framework-class-library-extension's Introduction

Framework Class Library Extension (FCL Extension)

THIS LIBRARY WILL BECOME DEPRECATED AND IS SUCCEEDED BY SEPARATE NEW LIBRARIES:

  • .NET Standard Library Extension: Core classes which target .NET Standard.
  • .NET Core Library Extension: Core classes which target .NET Core, supporting additional functionality not available on all .NET Standard platforms.
  • The remaining functionality (e.g., Interop, PresentationFramework helpers for MVVM) will be ported to separate libraries once I find the time.

The Framework Class Library Extension project contains highly reuseable classes I find to be missing in .NET's FCL. Since some of the implementations I blog about start to use a lot of code from this library, I decided to make it public so people can just access the entire library instead of small separate code samples. It was becoming a burden posting all dependent code for my code samples.

Assemblies from the original FCL are followed as much as possible:

  • Whathecode.System extends on System, System.Core and WindowsBase.
  • Whathecode.PresentationFramework extends on PresentationCore and PresentationFramework.

Namespaces from the original FCL are followed as much as possible:

  • Helper classes are contained within the corresponding namespace. E.g. A helper class for System.Diagnostics.Process will be located in Whathecode.System.Diagnostics.ProcessHelper.
  • Whole reuseable helper APIs are located in the relevant namespace. E.g. An abstract input controller is located in Whathecode.System.Windows.Input.InputController.
  • Linq extensions are located in Whathecode.System.Linq.
  • Extension methods are placed in an Extension namespace in the relevant namespace. E.g. general extension are located in Whathecode.System.Extensions, while extension methods when doing reflection are located in Whathecode.System.Reflection.Extensions.
  • Unit tests are placed in a Tests namespace in the relevant namespace. MSTest is used. These tests also serve as examples.
  • Aspects are placed in an Aspects namespace in the relevant namespace. In order to use them PostSharp is required, but no other code is dependent on those projects.

The library also contains unproven toy classes, which I still have to experiment with to judge their usefulness. They are located within *.Experimental namespaces.

Some classes do runtime code compilation which was made possible thanks to the excellent RunSharp library of Stefan Simik. It really simplifies Reflection.Emit.

Copyright (c) 2011 Steven Jeuris The library is distributed under the terms of the MIT license (http://opensource.org/licenses/mit-license). More information can be found in "LICENSE.txt"

framework-class-library-extension's People

Contributors

dominkomin avatar whathecode avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

framework-class-library-extension's Issues

Attached properties not fully supported in dependency property factory

I'm extending the support for creating dependency properties through the dependency property factory (DP factory), including allowing to set AffectsMeasure, etc .. in FrameworkElementMetaData.

However, since the DP factory requires attributes to be placed on a get and set method for attached properties, the way to implement attached properties is starting to deviate more and more from normal properties.

Possibly support for attached properties should be removed entirely, or a better way to support them should be found.

Command binding does not work with ElementName and Path attributes.

When a current data context has to be escaped by usage of the ElementName and Path attributes, following exception is thrown during compilation:

"Invalid path "DataContext.BaseActivity" for object of type "Laevo.ViewModel.Activity.WorkIntervalViewModel".\r\nParameter name: path"

Code example in WorkIntervalControl:

<DataTemplate DataType="userVm:UserViewModel">
    <user:UserImage
            behaviors:MouseBehavior.LeftClickCommand="{wtc:CommandBinding {x:Static b:Commands.OpenTimeLineSharing}, ElementName=Control, Path=DataContext.BaseActivity}" />
</DataTemplate>

Can't bind to property created by aspect supported dependency property factory

Sometimes binding properties within Xaml, created by the aspects version of the dependency property factory (WpfControl) throws the following exception: "A 'Binding' cannot be set on the 'Standard' property of type 'TestControl'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject."

The full stack trace of the failing unit test, XamlInitializationTest:

Initialization method Whathecode.Tests.System.Windows.DependencyPropertyFactory.Aspects.XamlTest.InitializeTest threw exception. System.Reflection.TargetInvocationException: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Windows.Markup.XamlParseException: A 'Binding' cannot be set on the 'Standard' property of type 'TestControl'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject..
    at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
   at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri)
   at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)
   at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
   at XamlTests.Aspects.XamlControl.InitializeComponent() in XamlControl.xaml: line 1
   at XamlTests.Aspects.XamlControl..ctor() in XamlControl.xaml.cs: line 11
 --- End of inner exception stack trace ---
    at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, ref Boolean canBeCached, ref RuntimeMethodHandleInternal ctor, ref Boolean bNeedSecurityCheck)
   at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, ref StackCrawlMark stackMark)
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, ref StackCrawlMark stackMark)
   at System.Activator.CreateInstance()
   at Whathecode.Tests.System.Windows.DependencyPropertyFactory.BaseXamlTest`1.InitializeTest() in BaseXamlTest.cs: line 15

The unit test somehow only seems to fail when ran individually, so I expect there to be some remnant state within the aspects which causes/prevents the problem from occurring.

InitializeEventHandlers OnDeserializing

The constructor is not called for objects which are deserialized. This means event handlers are not initialized for deserialized objects.

I slightly improved on the current solution by also initializing the events in a OnDeserializing method when it is present (OnDeserializingAttribute), however, this method needs to be injected in case it is not present yet.

InitializeEventHandlers aspect does not work with generic event handlers.

anupheaus reported a scenario in which the InitializeEventHandlers aspect fails: http://whathecode.wordpress.com/2012/03/26/null-checks-for-event-handlers-an-aspect-solution/#comment-195

I already created a unit test to test this scenario.

The problem is when RuntimeInitialize() is called we don’t know yet with which generic arguments the class will be initialized. We can only get information about those generic parameters and their constraints, variance information, …

However when OnConstructorEntry() is called we do have this information. We can get the actual (non-generic) type by calling GetType() on Instance from the MethodExecutionArgs parameter passed by PostSharp.

One solution would be doing all the reflection/runtime compilation work in OnConstructorEntry(), but this is something I wanted to avoid by compiling _addEmptyEventHandler once and reusing it for all instances.

I’ll have to think about a solution which uses a more complex ‘addEmptyEventHandler’ method which takes type arguments passed during OnConstructorEntry().

WPFControl aspect only initializes property factory at instance runtime.

There are some problems with template binding not working since the WPFControl aspect only initializes the dependency property factory at instance runtime. This was done in order to support generics, where the type parameters are only known at instance runtime.

Can this be circumvented, perhaps in newer versions of PostSharp?

User32.SendMessageTimeout return value cannot be marshalled

When trying to call SendMessageTimeout on a 64-bit PixelSense Surface, I received a runtime exception that the return type could not be marshalled.

I managed to resolve it by changing the return type from int to IntPtr. Why did this work before, on my 64bit laptop?

Verify for invalid flags when using coercion in DependencyPropertyFactory

Right now the static constructor of AbstractControlCoercion checks whether each value within the enum specifying the enum values is a separate flag. This is required for the DependencyPropertyFactory to correctly identify which are the dependent properties.

However, this check does not occur when implementing from IControlCoercion. Should we enforce that all users of the DependencyPropertyFactory have fully valid flag enums? For most use cases (when not using coercion) this might make using the enums overly complex.

I attempted to implement letting coercion use an array of enum values, rather than flags, but this seemingly failed during type construction in AbstractBehaviorAttribute.

InitializeEventHandlers aspect with events defined in interfaces

When there is an interface which defines an event within the assembly targeted by the InitializeEventHandlers aspect, compilation fails.

Unhandled exception (4.0.34.0, 32 bit, CLR 4.5, Release): System.NullReferenceException: Object reference not set to an instance of an object.
at PostSharp.Sdk.AspectInfrastructure.TypeInitializationManager.^nCElfVTrtpDd.^Dpi1V+WW(MethodDefDeclaration _0)
...

A current workaround is to exclude the particular event in question by using [InitializeEventHandlers( AttributeExclude = true)]. This does not seem the aspect from being applied to implementing classes.

Command binding does not work with a custom dependency property of ICommand type.

When I developed a custom user control that exposes a custom dependency property of ICommand type the exception is shown saying "there is no ID for given dependency property".

[DependencyProperty( Properties.OpenNotificationsCommand)]
public ICommand OpenNotificationsCommand { get; set; }

Maybe it is caused by the aspect [WpfControl( typeof( Properties ) )] which does not allow to expose commands ID's (Property of a command type is not accepted?).

Possible workaround solution is to use a control template and then template bindings. In that case exception is not thrown.

CommandBinding does not work in styles.

When using CommandBinding in a style setter an exception containing the following message is thrown:

"The only supported MarkupExtension types are DynamicResourceExtension and BindingBase or derived types."

Example code:

<Style
    x:Key="EditButton"
    TargetType="Image"
    BasedOn="{StaticResource CommandButton}">
        <Setter Property="Source" Value="../Activity/ActionIcons/edit.png" />
        <Setter Property="behaviors:MouseBehavior.LeftClickCommand" Value="{wtc:CommandBinding {x:Static b:Commands.EditActivity}}" />
</Style>

Command binding with optional parameters.

When trying to bind to commands of which the method definition contains an optional parameter an exception is currently thrown.

The command binding logic probably just needs to take optional parameters into account.

Condition converter does not work with the control template and Template binding.

When I try to use the Condition Converter (or Single Condition Converter) inside of a Control Template with a Template binding following exception is thrown:
"Set property 'System.Windows.TemplateBindingExtension.Converter' threw an exception. Object of type 'Whathecode.System.Windows.Data.SingleConditionConverterExtension' cannot be converted to type 'System.Windows.Data.IValueConverter'."

Stack trace:
System.Windows.Markup.XamlParseException occurred
HResult=-2146233087
Message=Set property 'System.Windows.TemplateBindingExtension.Converter' threw an exception.
Source=PresentationFramework
LineNumber=0
LinePosition=0
StackTrace:
at System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlReader templateReader, XamlObjectWriter currentWriter)
InnerException: System.ArgumentException
HResult=-2147024809
Message=Object of type 'Whathecode.System.Windows.Data.SingleConditionConverterExtension' cannot be converted to type 'System.Windows.Data.IValueConverter'.
Source=mscorlib
StackTrace:
at System.RuntimeType.TryChangeType(Object value, Binder binder, CultureInfo culture, Boolean needsSpecialCast)
at System.Reflection.MethodBase.CheckArguments(Object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig)
at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at System.Xaml.Schema.SafeReflectionInvoker.InvokeMethodCritical(MethodInfo method, Object instance, Object[] args)
at MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(Object inst, XamlMember property, Object value)
InnerException:

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.