Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I take a GUID as an attribute parameter?

I need a Guid property in some attribute class like this:

public class SomeAttribute : Attribute {
    private Guid foreignIdentificator;
    public Guid ForeignIdentificator {
        get { return this.foreignIdentificator; }
        set { this.foreignIdentificator = value; }
    }
}

But in attribute definition I can use only primitive types, which are constants ( I understand why, and it's make me sense ). The workaround can be definition "ForeignIdentificator" as string, and creating Guid in runtime:

public class SomeAttribute : Attribute {
    private string foreignIdentificator;
    public string ForeignIdentificator {
        get { return this.foreignIdentificator; }
        set { this.foreignIdentificator = value; }
    }
    public Guid ForeignIdentificatorGuid {
        get { return new Guid( ForeignIdentificator ); }
    }
}

Unahppily I loose check for type safety. The "ForeignIdentificator" property can contains any string value and during creating Guid will be thrown exception at runtime, not at compile time.

I know the compiler checks string value for "System.Runtime.InteropServices.GuidAttribute" for "Guid compatibility". This check is exactly what I need, but I don't know if this check i hardcoded in compiler or can me explicitly defined ( and how ).

Do you know some way, how to secure "Guid compatibilty" check for attributes? Or some another way, how to reach type safe Guid definition in attributes? Thanks.

like image 505
TcKs Avatar asked Nov 28 '08 13:11

TcKs


People also ask

How to send GUID as parameter in c#?

Use the CStr(System. Object) built-in conversion function to convert the Guid to String for the ValueMember property of the report parameter AvailableValues. When using Guid DataSourceParameter and its value is set to a ReportParameter, create an User Function to handle the conversion: cs.

Is GUID a reference type?

Guid is a Value Type. See MSDN.

Is a GUID a string?

A GUID is a 16-byte (128-bit) number, typically represented by a 32-character hexadecimal string.

What is the use of GUID in C#?

A GUID is a 128-bit integer (16 bytes) that can be used across all computers and networks wherever a unique identifier is required. Such an identifier has a very low probability of being duplicated.


2 Answers

I have run into your exact problem in the past. We simply required them to pass in the GUID as a string... the default way that the VS GUID generator tool gives it to us (*F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4). We essentially did what you did. We use it in a plug-in architecture, so our customers have been the ones to use the interface. If you look at what Microsoft does when they need to do the same thing, they do that.

It hasn't been a problem to do it this way. Not once, have we seen this as an issue from the field.

You might want to name that string field GUID, though, as to not confuse your consumers. Add some documentation in case they don't know what format it needs to be in.

I had the same reaction when I looked at this... but then I just moved on, as it seems there is no type-safe solution.

like image 107
Brian Genisio Avatar answered Sep 16 '22 21:09

Brian Genisio


Attribute parameters must be constant. If I break the rules, my C# compiler gives this error:

An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type

Since there are no GUID literals in C#, you have to encode the the GUID in another format, for example a string. However, you're not completely at sea: you can make your attribute have a ctor that takes the format you want. Here's an example with the same ctors as System.Guid:

[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
sealed class MyGuidAttribute : Attribute
{
    public Guid Guid { get; private set; }

    //
    // Summary:
    //     Initializes a new instance of the System.Guid class using the specified array
    //     of bytes.
    //
    // Parameters:
    //   b:
    //     A 16 element byte array containing values with which to initialize the GUID.
    //
    // Exceptions:
    //   System.ArgumentNullException:
    //     b is null.
    //
    //   System.ArgumentException:
    //     b is not 16 bytes long.
    public MyGuidAttribute(byte[] b)
    {
        this.Guid = new Guid(b);
    }
    //
    // Summary:
    //     Initializes a new instance of the System.Guid class using the value represented
    //     by the specified string.
    //
    // Parameters:
    //   g:
    //     A System.String that contains a GUID in one of the following formats ('d'
    //     represents a hexadecimal digit whose case is ignored): 32 contiguous digits:
    //     dddddddddddddddddddddddddddddddd -or- Groups of 8, 4, 4, 4, and 12 digits
    //     with hyphens between the groups. The entire GUID can optionally be enclosed
    //     in matching braces or parentheses: dddddddd-dddd-dddd-dddd-dddddddddddd -or-
    //     {dddddddd-dddd-dddd-dddd-dddddddddddd} -or- (dddddddd-dddd-dddd-dddd-dddddddddddd)
    //     -or- Groups of 8, 4, and 4 digits, and a subset of eight groups of 2 digits,
    //     with each group prefixed by "0x" or "0X", and separated by commas. The entire
    //     GUID, as well as the subset, is enclosed in matching braces: {0xdddddddd,
    //     0xdddd, 0xdddd,{0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd}} All braces, commas,
    //     and "0x" prefixes are required. All embedded spaces are ignored. All leading
    //     zeroes in a group are ignored.  The digits shown in a group are the maximum
    //     number of meaningful digits that can appear in that group. You can specify
    //     from 1 to the number of digits shown for a group. The specified digits are
    //     assumed to be the low order digits of the group.
    //
    // Exceptions:
    //   System.ArgumentNullException:
    //     g is null.
    //
    //   System.FormatException:
    //     The format of g is invalid.
    //
    //   System.OverflowException:
    //     The format of g is invalid.
    public MyGuidAttribute(string g)
    {
        this.Guid = new Guid(g);
    }
    //
    // Summary:
    //     Initializes a new instance of the System.Guid class using the specified integers
    //     and byte array.
    //
    // Parameters:
    //   a:
    //     The first 4 bytes of the GUID.
    //
    //   b:
    //     The next 2 bytes of the GUID.
    //
    //   c:
    //     The next 2 bytes of the GUID.
    //
    //   d:
    //     The remaining 8 bytes of the GUID.
    //
    // Exceptions:
    //   System.ArgumentNullException:
    //     d is null.
    //
    //   System.ArgumentException:
    //     d is not 8 bytes long.
    public MyGuidAttribute(int a, short b, short c, byte[] d)
    {
        this.Guid = new Guid(a, b, c, d);
    }
    //
    // Summary:
    //     Initializes a new instance of the System.Guid class using the specified integers
    //     and bytes.
    //
    // Parameters:
    //   a:
    //     The first 4 bytes of the GUID.
    //
    //   b:
    //     The next 2 bytes of the GUID.
    //
    //   c:
    //     The next 2 bytes of the GUID.
    //
    //   d:
    //     The next byte of the GUID.
    //
    //   e:
    //     The next byte of the GUID.
    //
    //   f:
    //     The next byte of the GUID.
    //
    //   g:
    //     The next byte of the GUID.
    //
    //   h:
    //     The next byte of the GUID.
    //
    //   i:
    //     The next byte of the GUID.
    //
    //   j:
    //     The next byte of the GUID.
    //
    //   k:
    //     The next byte of the GUID.
    public MyGuidAttribute(int a, short b, short c, byte d, byte e, byte f, byte g, byte h, byte i, byte j, byte k)
    {
        this.Guid = new Guid(a, b, c, d, e, f, g, h, i, j, k);
    }
    //
    // Summary:
    //     Initializes a new instance of the System.Guid class using the specified unsigned
    //     integers and bytes.
    //
    // Parameters:
    //   a:
    //     The first 4 bytes of the GUID.
    //
    //   b:
    //     The next 2 bytes of the GUID.
    //
    //   c:
    //     The next 2 bytes of the GUID.
    //
    //   d:
    //     The next byte of the GUID.
    //
    //   e:
    //     The next byte of the GUID.
    //
    //   f:
    //     The next byte of the GUID.
    //
    //   g:
    //     The next byte of the GUID.
    //
    //   h:
    //     The next byte of the GUID.
    //
    //   i:
    //     The next byte of the GUID.
    //
    //   j:
    //     The next byte of the GUID.
    //
    //   k:
    //     The next byte of the GUID.
    [CLSCompliant(false)]
    public MyGuidAttribute(uint a, ushort b, ushort c, byte d, byte e, byte f, byte g, byte h, byte i, byte j, byte k)
    {
        this.Guid = new Guid(a, b, c, d, e, f, g, h, i, j, k);
    }
}
like image 44
Jay Bazuzi Avatar answered Sep 18 '22 21:09

Jay Bazuzi