Thanks to visit codestin.com
Credit goes to github.com

Skip to content

System.Attribute F# snippets #7522

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//<Snippet1>
open System

// An enumeration of animals. Start at 1 (0 = uninitialized).
type Animal =
| Dog = 1
| Cat = 2
| Bird = 3

// A custom attribute to allow a target to have a pet.
type AnimalTypeAttribute(pet) =
inherit Attribute()
member val Pet = pet with get, set

// A test class where each method has its own pet.
type AnimalTypeTestClass() =
[<AnimalType(Animal.Dog)>]
member _.DogMethod() = ()

[<AnimalType(Animal.Cat)>]
member _.CatMethod() = ()

[<AnimalType(Animal.Bird)>]
member _.BirdMethod() = ()

let testClass = AnimalTypeTestClass()
let clsType = testClass.GetType()
// Iterate through all the methods of the class.
for mInfo in clsType.GetMethods() do
// Iterate through all the Attributes for each method.
for attr in Attribute.GetCustomAttributes mInfo do
// Check for the AnimalType attribute.
if attr.GetType() = typeof<AnimalTypeAttribute> then
printfn $"Method {mInfo.Name} has a pet {(attr :?> AnimalTypeAttribute).Pet} attribute."

// Output:
// Method DogMethod has a pet Dog attribute.
// Method CatMethod has a pet Cat attribute.
// Method BirdMethod has a pet Bird attribute.

//</Snippet1>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="customattribute.fs" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module ca1

// <Snippet1>
open System
open System.Reflection

[<assembly: AssemblyTitle "CustAttrs1CS">]
[<assembly: AssemblyDescription "GetCustomAttributes() Demo">]
[<assembly: AssemblyCompany"Microsoft">]
do ()

type Example = class end

// Get the Assembly object to access its metadata.
let assembly = typeof<Example>.Assembly

// Iterate through the attributes for the assembly.
for attr in Attribute.GetCustomAttributes assembly do
match attr with
// Check for the AssemblyTitle attribute.
| :? AssemblyTitleAttribute as attr ->
printfn $"Assembly title is \"{attr.Title}\"."
// Check for the AssemblyDescription attribute.
| :? AssemblyDescriptionAttribute as attr ->
printfn $"Assembly description is \"{attr.Description}\"."
// Check for the AssemblyCompany attribute.
| :? AssemblyCompanyAttribute as attr ->
printfn $"Assembly company is {attr.Company}."
| _ -> ()

// The example displays the following output:
// Assembly title is "CustAttrs1CS".
// Assembly description is "GetCustomAttributes() Demo".
// Assembly company is Microsoft.
// </Snippet1>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
module ca2

// <Snippet2>
open System
open System.ComponentModel

// Assign some attributes to the module.
[<``module``: Description "A sample description">]

// Set the module's CLSCompliant attribute to false
// The CLSCompliant attribute is applicable for /target:module.
[<``module``: CLSCompliant false>]
do ()

type DemoClass = class end

// Get the Module type to access its metadata.
let ilmodule = typeof<DemoClass>.Module

// Iterate through all the attributes for the module.
for attr in Attribute.GetCustomAttributes ilmodule do
match attr with
// Check for the Description attribute.
| :? DescriptionAttribute as attr ->
printfn $"Module {ilmodule.Name} has the description \"{attr.Description}\"."

// Check for the CLSCompliant attribute.
| :? CLSCompliantAttribute as attr ->
printfn $"""Module {ilmodule.Name} {if attr.IsCompliant then "is" else "is not"} CLSCompliant."""
| _ -> ()

// Output:
// Module CustAttrs2CS.exe is not CLSCompliant.
// Module CustAttrs2CS.exe has the description "A sample description".

// </Snippet2>
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
module ca4

// <Snippet4>
open System
open System.Runtime.InteropServices

// Define an enumeration of Win32 unmanaged types
type UnmanagedType =
| User = 0
| GDI = 1
| Kernel = 2
| Shell = 3
| Networking = 4
| Multimedia = 5

// Define the Unmanaged attribute.
type UnmanagedAttribute(unmanagedType) =
inherit Attribute()

// Define a property to get and set the UnmanagedType value.
member val Win32Type = unmanagedType with get, set

// Create a module for an imported Win32 unmanaged function.
module Win32 =
[<DllImport("user32.dll", CharSet = CharSet.Unicode)>]
extern int MessageBox(IntPtr hWnd, String text, String caption, uint ``type``)

type AClass() =
// Add some attributes to Win32CallMethod.
[<Obsolete "This method is obsolete. Use managed MsgBox instead.">]
[<Unmanaged(UnmanagedType.User)>]
member _.Win32CallMethod () =
Win32.MessageBox(0, "This is an unmanaged call.", "Caution!", 0u)

// Get the AClass type to access its metadata.
let clsType = typeof<AClass>
// Get the type information for Win32CallMethod.
let mInfo = clsType.GetMethod "Win32CallMethod"
if mInfo <> null then
// Iterate through all the attributes of the method.
for attr in Attribute.GetCustomAttributes mInfo do
match attr with
// Check for the Obsolete attribute.
| :? ObsoleteAttribute as attr ->
printfn $"Method {mInfo.Name} is obsolete. The message is:"
printfn $" \"{attr.Message}\""

// Check for the Unmanaged attribute.
| :? UnmanagedAttribute as attr ->
printfn "This method calls unmanaged code."
printfn $"The Unmanaged attribute type is {attr.Win32Type}."
let myCls = AClass()
myCls.Win32CallMethod() |> ignore
| _ -> ()

// This code example produces the following results.
//
// First, the compilation yields the warning, "... This method is
// obsolete. Use managed MsgBox instead."
// Second, execution yields a message box with a title of "Caution!"
// and message text of "This is an unmanaged call."
// Third, the following text is displayed in the console window:

// Method Win32CallMethod is obsolete. The message is:
// "This method is obsolete. Use managed MsgBox instead."
// This method calls unmanaged code.
// The Unmanaged attribute type is User.

// </Snippet4>
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
module ca5

// <Snippet5>
open System
open System.Reflection
open System.ComponentModel

type AClass() =
member _.ParamArrayAndDesc(
// Add ParamArray and Description attributes.
[<Description "This argument is a ParamArray">]
[<ParamArray>]
args: int[]) = ()

// Get the Class type to access its metadata.
let clsType = typeof<AClass>

// Get the type information for the method.
let mInfo = clsType.GetMethod "ParamArrayAndDesc"
if mInfo <> null then
// Get the parameter information.
let pInfo = mInfo.GetParameters()
if pInfo <> null then
// Iterate through all the attributes for the parameter.
for attr in Attribute.GetCustomAttributes pInfo[0] do
match attr with
// Check for the ParamArray attribute.
| :? ParamArrayAttribute ->
printfn $"Parameter {pInfo[0].Name} for method {mInfo.Name} has the ParamArray attribute."

// Check for the Description attribute.
| :? DescriptionAttribute as attr ->
printfn $"Parameter {pInfo[0].Name} for method {mInfo.Name} has a description attribute."
printfn $"The description is: \"{attr.Description}\""
| _ -> ()

// Output:
// Parameter args for method ParamArrayAndDesc has a description attribute.
// The description is: "This argument is a ParamArray"
// Parameter args for method ParamArrayAndDesc has the ParamArray attribute.

// </Snippet5>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="ca1.fs" />
<Compile Include="ca4.fs" />
<Compile Include="ca2.fs" />
<Compile Include="ca5.fs" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="hashcode.fs" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// <Snippet1>
open System
open System.Reflection
open System.Collections.Generic

// A custom attribute to allow two authors per method.
[<AllowNullLiteral>]
type AuthorsAttribute(authorName1, authorName2) =
inherit Attribute()

member val AuthorName1 = authorName1
member val AuthorName2 = authorName2

// Use the hash code of the string objects and xor them together.
override _.GetHashCode() =
authorName1.GetHashCode() ^^^ authorName2.GetHashCode()

// Provide the author names for each method of the class.
type TestClass() =
[<Authors("Immanuel Kant", "Lao Tzu")>]
member _.Method1() = ()

[<Authors("Jean-Paul Sartre", "Friedrich Nietzsche")>]
member _.Method2() = ()

[<Authors("Immanuel Kant", "Lao Tzu")>]
member _.Method3() = ()

[<Authors("Jean-Paul Sartre", "Friedrich Nietzsche")>]
member _.Method4() = ()

[<Authors("Immanuel Kant", "Friedrich Nietzsche")>]
member _.Method5() = ()

// Get the class type to access its metadata.
let clsType = typeof<TestClass>

// Store author information in a array of tuples.
let authorsInfo =
[ // Iterate through all the methods of the class.
for method in clsType.GetMethods() do
// Get the Authors attribute for the method if it exists.
let authAttr =
Attribute.GetCustomAttribute(method, typeof<AuthorsAttribute>) :?> AuthorsAttribute

if authAttr <> null then
// Add the information to the author list.
$"{clsType.Name}.{method.Name}", authAttr ]

// Iterate through the list
printfn "Method authors:\n"

authorsInfo
|> List.groupBy (fun (_, authors) -> authors.AuthorName1, authors.AuthorName2)
|> List.iter (fun ((name1, name2), authors) ->
printfn $"{name1} and {name2}"
for (methodName, _) in authors do
printfn $" {methodName}")

// The example displays the following output:
// Method authors:
//
// Immanuel Kant and Lao Tzu
// TestClass.Method1
// TestClass.Method3
// Jean-Paul Sartre and Friedrich Nietzsche
// TestClass.Method2
// TestClass.Method4
// Immanuel Kant and Friedrich Nietzsche
// TestClass.Method5
// </Snippet1>
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// <Snippet1>
open System

// An enumeration of animals. Start at 1 (0 = uninitialized).
type Animal =
| Dog = 1
| Cat = 2
| Bird = 3

// A custom attribute to allow a target to have a pet.
type AnimalTypeAttribute(pet) =
inherit Attribute()

member val Pet = pet

// Override IsDefaultAttribute to return the correct response.
override _.IsDefaultAttribute() =
pet = Animal.Dog

// Provide a default constructor and make Dog the default.
new() = AnimalTypeAttribute Animal.Dog

type TestClass() =
// Use the default constructor.
[<AnimalType>]
member _.Method1() = ()

// Get the class type to access its metadata.
let clsType = typeof<TestClass>

// Get type information for the method.
let mInfo = clsType.GetMethod "Method1"

// Get the AnimalType attribute for the method.
let atAttr =
Attribute.GetCustomAttribute(mInfo, typeof<AnimalTypeAttribute>)
:?> AnimalTypeAttribute

// Check to see if the default attribute is applied.
printf $"The attribute {atAttr.Pet} for method {mInfo.Name} in class {clsType.Name} "
printfn $"""{if atAttr.IsDefaultAttribute() then "is" else "is not"} the default for the AnimalType attribute."""

// Output:
// The attribute Dog for method Method1 in class TestClass is the default for the AnimalType attribute.

// </Snippet1>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="defattr.fs" />
</ItemGroup>
</Project>
Loading