Reputation: 1211
I have several C# projects that are in some sense a unit. There are several common AssemblyInfo attributes that make sense to share among them (for example company name). So I made a shared file that all projects include, containing (for example) AssemblyCompany
:
[assembly: AssemblyCompany("Acme Inc.")]
And I removed the corresponding attributes from each project's individual AssemblyInfo.cs.
This all worked well, but I'd like to go a step further in one case: copyright. The first year of publication varies from project to project, and so they really should have different copyright strings. So I'd like to do something like this in the shared file:
[assembly: AssemblyCopyright(string.Format("Copyright {$0} Acme Inc.", Acme.AssemblyInfo.FirstPublicationYear)]
And then have each individual project defining its own particular Acme.AssemblyInfo.FirstPublicationYear
.
I have taken a couple different shots in the dark. First, I just tried defining a const in a static class in a project's AssemblyInfo.cs:
namespace Acme
{
public static class AssemblyInfo
{
public const int FirstPublicationYear = 2015;
}
}
This results in the error "An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type". So I tried making an attribute class:
namespace Acme
{
using System;
[AttributeUsage(AttributeTargets.Assembly)]
public class FirstPublicationYearAttribute : Attribute
{
private int year;
public FirstPublicationYearAttribute(int year)
{
this.year = year;
}
}
}
Added that attribute to an individual project's AssemblyInfo.cs:
[assembly: Acme.FirstPublicationYear(2015)]
But I'm not sure how to (or even if I can) appropriately change the AssemblyCopyright
line in the shared properties file. I've tried a couple ways that haven't worked. First:
[assembly: AssemblyCopyright(string.Format("Copyright © {$0} Acme, Inc.", Acme.FirstPublicationYear))]
... which tells me FirstPublicationYear
does not exist in the namespace Acme
. So I thought maybe I'd make it look more like an attribute:
[assembly: AssemblyCopyright(string.Format("Copyright © {$0} Acme, Inc.", [assembly: Acme.FirstPublicationYear]))]
... which tells me "Invalid expression term '['".
Is there a way to accomplish what I'm trying to do here? Thanks.
Upvotes: 0
Views: 2172
Reputation: 10708
There is no good way to accomplish this using code. The reason is that Attributes must have compile-time values to properly output the data to the resulting file, and there is thus no way to logically build them from parts, because that build is by definition a run-time, not compile-time, operation.
EDIT: It does turn out to be possible to concatenate strings using +
operators, even at compile time, so long as all the strings being concatenated are themselves constant. See Frank's answer.
However, because all these values come from a single shared file, it is possible to do this by writing a prebuild batch file. I have implemented this as far as production code as a simple call in the prebuild step, with said helper being written in C#. As long as the output file (usually AssemblyInfo.cs
) is ignored by your repo (and if you're not using a repo, switch to one) you'll be able to rely on that file being generated by the prebuild, and then found by the compiler, even though it's not actually being copied down.
Upvotes: 0
Reputation: 4481
Instead of using string.Format
, just try concatenating it:
"Copyright" + Acme.AssemblyInfo.FirstPublicationYear + "Acme Inc."
The compiler will be able to make a compile time constant from this.
Upvotes: 1