Magnus Mårtensson
Microsoft Regional Director, Azure MVP, CEO Loftysoft
Avirag Jain
Director & CTO R Systems
Mahesh Chand
Founder C# Corner, CEO Mindcracker
Chris Gali
CEO & Co-Founder Graphite
Subinder Khurana
Chief Architect StoryProcess, Founder NASSCOM DeepTech Club
Bryan Rishforth
Investor, Chairman Graphite
Bryn Everson
Director Biz Dev Graphite
Raj Tiwari
Digital Transformation Leader, Futurist and Visionary
Joseph Guadagno
Microsoft MVP, Lead Quicken Loans
Nikita Sachdev
Entrepreneur, Blockchain Enthusiast & Advisor, Social Media Influencer
Doug Wagner
COO & Founder Adapt Technical Group
Ritesh Modi
Architect, Senior Evangelist, Cloud Architect
Crystal Wenrick
Director Communications Mindcracker
Allen O’Neill
Microsoft MVP, Consulting Engineer/Architect
Praveen Kumar
CEO MCN Solutions
Chris Love
Founder Love2Dev, Microsoft MVP, Author
Sanjay Vyas
Microsoft Regional Director, Microsoft MVP, Founder & CEO SkillLabs Technologies
Veena Sarda
Deep Learning Consultant, Author
Sekhar Srinivasan
C# Corner MVP, Microsoft Certified Trainer, Pluralsight Author
Lalit Bansal
Founder & CEO - EIY SYS
Navdeep Garg
CEO Revinfotech
Prakash Tripathi
Tech Manager/Leader, Microsoft MVP, Blogger
Bhavna Jain
Breakthrough Consultant
Naveen Sharma
Enterprise Architect, Leadership Coach, Author
Vidya Vrat Agarwal
Principal Architect, Microsoft MVP, Author
Sheetal Agarwal
Founder Clownselors, Medical Clown, Trainer
Abhishek Kant
Founder GTM Catalyst
Vishnu Saran
Founder & CEO VoiceQube
Sandeep Soni
Founder & CEO Deccansoft, Microsoft Certified Trainer
Parveen Malik
AVP InfoSec & Vulnerability Management, Information Security Expert
Nitin Pandit
Microsoft MVP, Developer Evangelist, Author
Niloshima Srivastava
C# Corner MVP, Tech Architect, Trainer, Blogger
Bala Chirtsabesan
Senior Software Engineer at Microsoft, Author
Manoj Mittal
Sr. Technical Architect, C# Corner MVP, Author
Chandni Di
Co-Founder Voice of Slum
Vithal Wadje
Technical Lead, Microsoft MVP, Author
Shivam Ahuja
Founder SkillCircle, Business Mentor
Chervine Bhiwoo
Solution Architect, Microsoft MVP, Author
Saurabh Jain
Vice President Paytm, Founder Fun2Do Labs, Author
Vinay Solanki
Head IoT at Lenovo, Founder IoT-NCR
Anshu kumari
Founder Blockchainkids, Inventor, Trainer
Amit Singal
CEO Startup Buddy
Dev Pratap
Co-Founder & CEO Voice of Slum
Amey Vartak
Technology Consultant, Full Stack Developer, C# Corner MVP, Author
Viswanatha Swamy
Principal Software Engineer, C# Corner MVP, Author
Sanket Verma
Research Engineer @ Ballistics (Forensics) and Chair, PyData Delhi
Sourabh Somani
Lead Developer, Microsoft MVP, Author
Abhishek Mishra
Software Architect, C# Corner MVP, Author
Siddharth Vaghasia
Technical Consultant, C# Corner MVP, Blogger
Bassam Alugili
Senior Software Specialist, Database Expert
S Ravi Kumar
Solution Architect, C# Corner MVP, Author
Sundaram Subramanian
Full Stack Developer, C# Corner MVP, Speaker
Deepesh Somani
Solution Architect, Microsoft MVP, Author
Debasis Saha
Technical Project Manager, C# Corner MVP, Blogger, Author
Vipul Jain
Software Architect, C# Corner MVP, Author
Akshay Patel
Technical Architect, Microsoft Certified Trainer, C# Corner MVP, Author
Stephen Simon
RPA Developer, Evangelist, Author
Vivek Sharma
Founder Kingster636, AR/VR Specialist
Jeetendra Gund
Technical Lead, C# Corner MVP, Author
Sujal Beniwal
AI Enthusiast, Student
M Viknaraj
Microsoft MVP, Azure Architect, Author
Prasham Sabadra
Software Architect, C# Corner MVP, Trainer, Author
Aakash Maurya
Senior Developer, C# Corner MVP, Speaker
Ankit Sharma
Senior Software Engineer, C# Corner MVP, Author
Mangesh Gaherwar
Team Lead, C# Corner MVP, Author
Viral Jain
Technical Consultant, C# Corner MVP, Author
Bhasker Das
Solution Architect, Evangelist
Manish Dwivedi
Associate Project Manager
Ck Nitin
Programmer, Author
Rohit Gupta
Technical Trainer, Author
Manish Tewatia
Full-stack Marketer, UX Designer
Bhavya Gaur
Technical Illustrator
Rohit Tomar
SEO/SMO Expert
Web Track
Cloud & Data Track
Dev Track
Registration & Breakfast
Future of Desktop Apps with JS (ElectronJs)
Nitin Pandit
Building Serverless Microservices Using Microsoft Azure
Vithal Wadje
Innovating RPA: A Robot for Every Person
Stephen Simon
Managing Cloud Storage Accounts using Logic Apps
Viknaraj Manogararajah
Data visualization using Python
Sekhar Srinivasan
Going Cross platform with AR Foundation
Vivek Sharma
Keynote
Managing your Azure dependencies in ASP.NET Core apps using VS
Bala Chirtsabesan
Securing Applications on Intelligent Azure
Abhishek Mishra
Getting started with Blazor the Framework of Future
S Ravi Kumar
Lunch
Build Progressive Web Apps using Angular 9
Debasis Saha
Build and deploy to any platform using Azure DevOps
Chervine Bhiwoo
Deep Dive in Azure Service Bus
Akshay Patel
Build a Native Mobile Application using React Native and JavaScript
Joseph Guadagno
Making sense of Web Job, Web Job SDK and Functions in Azure
Prakash Tripathi
CloudFront Distribution in AWS
Viral Jain
Tea Break
Introduction to PowerBI
Aakash Maurya
Build Advanced SPFx solutions with React and Graph API
Siddharth Vaghasia
Build Business Intelligence Analyst (BIA) Skills
Sundaram Subramanian
Deep dive of Power Platform – AI BUILDER
Prasham Sabadra
Panel 1
What's new in SharePoint development
Vipul Jain
Build a SSO (Single Sign On) based Native JavaScript application with Microsoft Identity within 10 minutes
Manoj Mittal
Panel 2
Applications and working of AI
Veena Sarda
Deploying serverless API's with .Net core 3.0 on AWS & Azure
Amey Vartak
Panel 3
Blockchain with .NET Core (Ark)
Anshu Kumari
Closing Note & Prize Distribution
Dev Track
Cloud Track
Architecture Track
Emerging Tech Track
Registration & Breakfast
Creating Full-Stack Web Apps Using Server-Side Blazor
Ankit Sharma
Real time face recognition with MS Cognitive Services
Niloshima Srivastava
Building Scalable APIs with GraphQL
Jeetendra Gund
Future of development with AI and Blockchain
Navdeep Garg
Debugging Tips and Tricks with Visual Studio 2019
Joseph Guadagno
Azure Containers
Abhishek Kant
Enterprise Architecture
Naveen Sharma
Bot Framework - learn it fast and look like a boss!
Allen O’Neill
Keynote
.Net Core & C# 8 Performance
David McCarter
Working with Azure kubernetes services
Ritesh Modi
Becoming an Architect
Vidyavrat Agarwal
Why Techies Need to Learn Product Management
Saurabh Jain
Lunch
Build a rules engine in .Net Core
Sanjay Vyas
Building CI and CD Pipeline using Azure DevOps
Sandeep Soni
Entity Framework Core - Tips and Tricks, Performance Optimization, and Tuning
Bassam Alugili
Hacking your way into Data Science
Sanket Verma
Speed up your .Net Core Website
Sourabh Somani
Azure
Magnus Mårtensson
Demystifying Open Distro for Elasticsearch
Suman Debnath
Future of Data
Shivam Ahuja
Tea Break
gRPC with C# and .Net Core
Mangesh Gaherwar
Panel 1
Essentials of Cloud security
Parveen Malik
Power platform and Dynamics 365
Deepesh Somani
Microservices - the gRPC Way
Viswanatha Swamy
Panel 2
Reserved
Reserved
Closing Note & Prize Distribution
How C# 11 Generic Attributes Make Metadata Type-Safe
Metadata often begins as a small convenience: an attribute identifies a handler, describes a route, marks a data source, or records the permissions required by a component. As an application grows, those annotations become part of its architecture. A typo in a string or an incorrect typeof argument can then cause a failure long after compilation.
C# 11 improves this area with generic attributes. Instead of passing a type through an unstructured constructor argument, an attribute can express the associated type directly in its declaration. Reflection, source generators, dependency injection, and validation code can then inspect metadata with a clearer contract.
This approach is useful in cloud services, web APIs, data pipelines, and desktop tools built by Australian teams working across Sydney, Melbourne, Brisbane, or Perth. It also fits systems that must handle privacy obligations, regional hosting decisions, and applications deployed to Azure Australia East or Azure Australia Southeast.
What Generic Attributes Add To C#
Before C# 11, an attribute that associated a class with a model or processor commonly accepted a Type value. The declaration worked, but the compiler could not enforce much about the relationship:
[Handler(typeof(OrderCreated))]
public sealed class OrderCreatedHandler
{
}
The attribute might be defined as follows:
public sealed class HandlerAttribute : Attribute
{
public HandlerAttribute(Type messageType)
{
MessageType = messageType;
}
public Type MessageType { get; }
}
The typeof expression is valid for any type, including one that the handler cannot process. A developer could accidentally associate OrderCreatedHandler with CustomerDeleted, and the error would appear only when registration or dispatch code examined the metadata.
A generic attribute moves the type into the attribute’s generic argument:
[Handler<OrderCreated>]
public sealed class OrderCreatedHandler
{
}
Its definition can constrain the type parameter:
public interface IMessage
{
}
public sealed class HandlerAttribute<TMessage> : Attribute
where TMessage : IMessage
{
}
Now the compiler rejects an attribute applied with a type that does not implement IMessage. The declaration documents the association directly, and refactoring tools can follow the type reference more reliably than a string or loosely interpreted constructor value.
Building A Useful Metadata Contract
A practical generic attribute should describe a stable architectural relationship. For example, a command handler can be paired with its command type, a serializer can be associated with a document model, or a policy can identify the resource it governs:
public interface ICommand
{
}
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public sealed class CommandHandlerAttribute<TCommand> : Attribute
where TCommand : ICommand
{
public CommandHandlerAttribute(string queueName)
{
QueueName = queueName;
}
public string QueueName { get; }
}
A handler might then be annotated like this:
public sealed record InvoiceApproved(Guid InvoiceId) : ICommand;
[CommandHandler<InvoiceApproved>("billing-events")]
public sealed class InvoiceApprovedHandler
{
}
The generic argument supplies type identity, while the constructor supplies additional constant metadata. Attribute constructor arguments must remain compatible with attribute rules: strings, primitive values, enums, Type values, arrays of supported values, and similar compile-time data. A generic attribute does not turn an attribute into a dependency injection container or permit arbitrary runtime objects.
Reflection needs a little care because a constructed generic attribute has a different runtime type:
var handlers = assembly.GetTypes()
.Where(type => type.GetCustomAttributes(inherit: false)
.Any(attribute =>
attribute.GetType().IsGenericType &&
attribute.GetType().GetGenericTypeDefinition() ==
typeof(CommandHandlerAttribute<>)));
Application code can inspect GetGenericArguments()[0] to discover the command type. For a larger system, a source generator may be preferable: it can scan the declarations at build time and produce a registration map without repeated reflection during startup.
That distinction matters for high-volume services. A small ASP.NET Core API may comfortably inspect metadata once while starting. A serverless function, a container with tight cold-start targets, or a service handling a large number of message contracts may benefit from generated registration. The attribute provides the contract; reflection or generation determines how the contract is consumed.
Choosing Between Old And New Patterns
Generic attributes are most valuable when the associated type is central to the meaning of the annotation. They are less useful when the type is incidental or when the metadata must be consumed by tools that do not understand generic attribute syntax.
| Requirement | Traditional Attribute | C# 11 Generic Attribute |
|---|---|---|
| Associate metadata with a model | typeof(Order) constructor argument |
[Metadata<Order>] |
| Compiler checks the model contract | Usually limited to a Type value |
Generic constraints can enforce it |
| Reflection lookup | Inspect a normal attribute property | Inspect the constructed generic type |
| Multiple associated types | Several Type properties |
Multiple generic parameters, where appropriate |
| Runtime flexibility | Easy to select types dynamically | Intended for compile-time-known types |
| Source-generator discovery | Possible, but conventions may be looser | Type relationships are explicit |
| Compatibility with older language versions | Broader | Requires C# 11 compiler support |
A conventional attribute can still be the better choice for configuration supplied by an administrator, a tenant, or a deployment environment. For example, a [RetryPolicy("standard")] annotation is naturally string-based if policies are loaded from configuration. Generic attributes are designed for compile-time type relationships, not values that change between environments.
There are also interoperability considerations. Generic attributes are supported by the C# compiler and modern .NET tooling, but a shared library may be consumed by older projects, analyzers, or reflection utilities. Teams maintaining long-lived enterprise software should verify compiler versions, CI images, test runners, and code-generation tools before standardising on the feature.
For teams designing cloud integrations, metadata often sits beside transport and storage decisions. A streaming architecture example can illustrate how contracts, processing components, and infrastructure boundaries interact, even though generic attributes should remain focused on describing the application’s type relationships.
Applying Type-Safe Metadata In Real Systems
A message bus is a natural use case. Suppose every command must have a validator and a handler. A generic attribute can identify the command while a convention locates the related services:
[AttributeUsage(AttributeTargets.Class)]
public sealed class ValidatedCommandAttribute<TCommand> : Attribute
where TCommand : ICommand
{
public ValidatedCommandAttribute(string validatorKey)
{
ValidatorKey = validatorKey;
}
public string ValidatorKey { get; }
}
The consuming code can ensure that the discovered handler and validator both support the generic command type. If a source generator processes these declarations, it can emit registrations such as:
services.AddScoped<IValidator<InvoiceApproved>,
InvoiceApprovedValidator>();
services.AddScoped<ICommandHandler<InvoiceApproved>,
InvoiceApprovedHandler>();
This reduces repeated registration code and makes missing relationships visible during a build or validation test. It also supports clearer diagnostics: an analyzer can report that a command has two handlers, no validator, or a handler whose generic interface does not match the attribute’s type argument.
Generic attributes can describe API capabilities as well. An endpoint marker might use [Produces<InvoiceSummary>] to identify a response model. A documentation generator could read that metadata and create OpenAPI descriptions, while a serializer registry could resolve the correct converter. The design should avoid duplicating information already available from method signatures, however. If the return type already expresses the response contract, another annotation may add noise rather than safety.
Australian applications add practical concerns to this design. A health, finance, or government workload may need to classify data under internal policies aligned with the Privacy Act 1988 and the Australian Privacy Principles. A generic attribute can associate a record type with a compile-time policy marker, but it cannot replace access controls, audit logging, retention rules, or a privacy impact assessment. Metadata should support those controls, never pretend to implement them.
Regional deployment can affect the values stored alongside the type. A service hosted in Azure Australia East may use a "au-east" region key, while a disaster-recovery deployment in Australia Southeast uses another. Keep environment-specific settings in configuration and use generic attributes for stable code-level relationships. This separation helps teams operating across Australian time zones avoid rebuilding an application merely to change a regional endpoint.
Practices For Reliable Generic Attribute Design
The feature is simple to write, but its value depends on disciplined contracts and predictable consumers. The following practices keep metadata useful as a codebase expands:
- Constrain generic parameters with meaningful interfaces or base classes.
- Use
AttributeUsageto control targets, inheritance, and duplicate declarations. - Keep runtime configuration out of generic arguments and attribute constructors where it changes by environment.
- Validate discovered metadata during application startup or in a build-time generator.
- Add tests covering reflection, duplicate registrations, missing handlers, and incompatible contracts.
Attribute names should communicate intent rather than implementation. CommandHandlerAttribute<TCommand> is clearer than TypeBindingAttribute<T>, because its purpose remains understandable when viewed in a stack trace or generated registration file. Generic parameter names such as TCommand, TModel, and TResource also make constraints easier to interpret.
Be deliberate with multiple generic parameters:
public sealed class MappingAttribute<TSource, TDestination> : Attribute
where TSource : class
where TDestination : class
{
}
[Mapping<Customer, CustomerDto>] is expressive when the mapping itself is a meaningful architectural declaration. It becomes harder to read when it encodes every option in a large set of type parameters. In that case, use a small number of generic arguments and named properties for stable, simple values.
A further safeguard is to make metadata validation part of CI. A test can scan all assemblies for generic attributes, verify their constraints and associated interfaces, and fail when a handler is missing. This is particularly helpful in distributed teams, where a developer in Melbourne may add a contract while a deployment pipeline in Sydney or Brisbane discovers registration problems later.
Making The Feature Work With Modern Tooling
Generic attributes fit naturally with source generators and analyzers. A generator can identify every constructed attribute whose generic type derives from a known base, extract the type arguments, and emit strongly typed code. The generated output can register handlers, build serializers, create documentation, or produce a diagnostics report.
Reflection remains appropriate when assemblies are loaded dynamically, such as plugin systems. In that case, avoid assuming every attribute is non-generic. Check IsGenericType, compare the generic type definition, and inspect constructor properties defensively. A plugin may reference a different version of a contract assembly or omit optional metadata, so failures should produce an actionable message rather than a vague activation exception.
For ASP.NET Core applications, generic attributes can complement endpoint conventions, but they should not obscure the routing model. For Azure Functions, queue consumers, and background workers, they can describe message-to-handler relationships while dependency injection manages object creation. For data platforms, they can associate schemas or converters with domain types, provided that schema evolution is handled separately through versioning rules.
C# 11 generic attributes provide their greatest benefit when metadata describes something the compiler can understand: a command belongs to a contract, a resource has a policy marker, or a model has a known converter. They replace fragile type references with declarations that are easier to refactor, validate, and generate against. Used with sensible constraints, startup checks, and environment-independent design, they turn annotations from passive labels into dependable parts of a type-safe .NET architecture.
1, CBD, Maharaj Surajmal Road, Near Yamuna Sports Complex, Delhi, 110032
GENERAL QUERIES
Manish Tewatia
manish@csharpcon.com
+91-9718-431-042
TICKET QUERIES
Atul Gupta
conference@csharpcon.com
+91-9910-125-804